我如何从C ++path中提取文件名和扩展名
我有一个存储在.log
中的文件列表,
c:\foto\foto2003\shadow.gif D:\etc\mom.jpg
我想从这个文件中提取名称和扩展名。 你能举一个简单的方法来做这个例子吗?
要提取没有扩展名的文件名,使用boost :: filesystem :: path :: stem而不是丑陋的std :: string :: find_last_of(“。”)
boost::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension : " << p.filename() << std::endl; // file.ext std::cout << "filename only : " << p.stem() << std::endl; // file
如果你想要一个安全的方式(即平台之间的便携式,而不是假设的道路上),我build议使用boost::filesystem
。
它会看起来像这样:
boost::filesystem::path my_path( filename );
然后你可以从这个path中提取各种数据。 这里是path对象的文档。
顺便说一句:还记得,为了使用path
c:\foto\foto2003\shadow.gif
你需要在string文字中转义\
const char* filename = "c:\\foto\\foto2003\\shadow.gif";
或者使用/
来代替:
const char* filename = "c:/foto/foto2003/shadow.gif";
这仅适用于在引号中指定文字string,从文件加载path时问题不存在。
你必须从std::string
文件中读取你的文件名。 您可以使用std::ostream
的string提取操作符。 一旦你的文件名在std::string
,你可以使用std::string::find_last_of
方法find最后一个分隔符。
像这样的东西:
std::ifstream input("file.log"); while (input) { std::string path; input >> path; size_t sep = path.find_last_of("\\/"); if (sep != std::string::npos) path = path.substr(sep + 1, path.size() - sep - 1); size_t dot = path.find_last_of("."); if (dot != std::string::npos) { std::string name = path.substr(0, dot); std::string ext = path.substr(dot, path.size() - dot); } else { std::string name = path; std::string ext = ""; } }
不是代码,但这里是这个想法:
- 从inputstream(
std::ifstream
)读取一个std::string
,每个读取的实例将是完整的path - 对string做一个
find_last_of
, - 从这个位置提取一个子string到最后,这会给你一个文件名
- 做一个
find_last_of
.
,而任何一方的子串都会给你名字+扩展名。
对于C ++ 17 :
#include <filesystem> std::filesystem::path p("c:/dir/dir/file.ext"); std::cout << "filename and extension: " << p.filename() << std::endl; // "file.ext" std::cout << "filename only: " << p.stem() << std::endl; // "file"
有关文件系统的参考: http : //en.cppreference.com/w/cpp/filesystem
- 的std ::文件系统::path::文件名
- 的std ::文件系统::path::干
正如@RoiDanto所build议的那样 ,对于输出格式, std::out
可以用引号括住输出,例如:
filename and extension: "file.ext"
你可以通过p.filename().string()
将std::filesystem::path
转换成std::filesystem::path
p.filename().string()
如果你需要的话,例如:
filename and extension: file.ext
我也使用这个片段来确定适当的斜线字符:
boost::filesystem::path slash("/"); boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();
然后用OS的首选斜杠replace斜杠。 如果你经常在Linux / Windows之间部署的话,这很有用。
对于linux或unix机器,os有两个处理path和文件名的函数。 使用man 3 basename来获得更多关于这些函数的信息。 使用系统提供的function的好处是你不必安装boost或需要编写自己的函数。
#include <libgen.h> char *dirname(char *path); char *basename(char *path);
手册页中的示例代码:
char *dirc, *basec, *bname, *dname; char *path = "/etc/passwd"; dirc = strdup(path); basec = strdup(path); dname = dirname(dirc); bname = basename(basec); printf("dirname=%s, basename=%s\n", dname, bname);
由于basename()函数的非const参数types,在C ++代码中使用这个有点不直接。 以下是我的代码库中的一个简单示例:
string getFileStem(const string& filePath) const { char* buff = new char[filePath.size()+1]; strcpy(buff, filePath.c_str()); string tmp = string(basename(buff)); string::size_type i = tmp.rfind('.'); if (i != string::npos) { tmp = tmp.substr(0,i); } delete[] buff; return tmp; }
新/删除的使用是不好的风格。 我可以把它放到一个try / catch块中,以防发生两次调用之间的事情。