我如何从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 = ""; } } 

不是代码,但这里是这个想法:

  1. 从inputstream( std::ifstream )读取一个std::string ,每个读取的实例将是完整的path
  2. 对string做一个find_last_of
  3. 从这个位置提取一个子string到最后,这会给你一个文件名
  4. 做一个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块中,以防发生两次调用之间的事情。