如何从C ++中的路径中提取文件名和扩展名

时间:2010-12-13 16:05:18

标签: c++ string file-io

我有一个以.log格式存储的文件列表:

c:\foto\foto2003\shadow.gif
D:\etc\mom.jpg

我想从这些文件中提取名称和扩展名。你能给出一个简单方法的例子吗?

9 个答案:

答案 0 :(得分:151)

要提取没有扩展名的文件名,请使用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

答案 1 :(得分:19)

如果您想要一种安全的方式(即在平台之间移植而不在路径上进行假设),我建议您使用boost::filesystem

看起来有点像这样:

boost::filesystem::path my_path( filename );

然后,您可以从此路径中提取各种数据。 Here's the documentation of path object.


顺便说一句:还要记住,为了使用像

这样的路径
c:\foto\foto2003\shadow.gif

你需要转义字符串文字中的\

const char* filename = "c:\\foto\\foto2003\\shadow.gif";

或者改为使用/

const char* filename = "c:/foto/foto2003/shadow.gif";

这仅适用于在""引号中指定文字字符串,从文件加载路径时问题不存在。

答案 2 :(得分:14)

您必须从std::string中的文件中读取您的文件名。您可以使用std::ostream的字符串提取运算符。在std::string中输入文件名后,您可以使用std::string::find_last_of方法查找最后一个分隔符。

这样的事情:

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  = "";
    }
}

答案 3 :(得分:12)

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

正如 @RoiDanto 所建议的那样,对于输出格式,std::out可能会在输出中包含引号,例如:

filename and extension: "file.ext"

如果您需要,可以std::filesystem::pathstd::string转换为p.filename().string(),例如:

filename and extension: file.ext

答案 4 :(得分:3)

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

  1. 从输入流(std::string)中读取std::ifstream,每个实例读取都将是完整路径
  2. find_last_of
  3. 的字符串执行\
  4. 从此位置提取子字符串到结尾,现在将为您提供文件名
  5. find_last_of执行.,并且任何一方的子字符串都会为您提供名称+扩展名。

答案 5 :(得分:0)

我还使用此片段来确定适当的斜杠字符:

boost::filesystem::path slash("/");
    boost::filesystem::path::string_type preferredSlash = slash.make_preferred().native();

然后用操作系统的首选斜杠替换斜杠。如果在Linux / Windows之间不断部署,则非常有用。

答案 6 :(得分:0)

对于linux或unix机器,os有两个处理路径和文件名的函数。使用man 3 basename获取有关这些函数的更多信息。 使用系统提供的功能的优点是您不必安装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参数类型,使用这个内部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;
}

使用new / delete不是好风格。我可以把它放入try / catch中 阻止两个电话之间发生的事情。

答案 7 :(得分:0)

尼古拉·默金(Nickolay Merkin)和钟雨辰(Yuchen Zhong)的回答很不错,但是从评论中您可以看到它并不完全准确。

打印时隐式转换为std :: string会将文件名括在引号中。评论也不正确。

path::filename()path::stem()返回新的路径对象,而path::string()返回对字符串的引用。因此,std::cout << file_path.filename().string() << "\n"之类的东西可能会导致悬挂参考的问题,因为参考指向的字符串可能已被破坏。

答案 8 :(得分:0)

尝试以下技巧,从c ++中没有扩展名的路径中提取文件名,而c ++中没有外部库:

#include <iostream>
#include <string>

using std::string;

string getFileName(const string& s) {
char sep = '/';
#ifdef _WIN32
sep = '\\';
#endif
size_t i = s.rfind(sep, s.length());
if (i != string::npos) 
{
string filename = s.substr(i+1, s.length() - i);
size_t lastindex = filename.find_last_of("."); 
string rawname = filename.substr(0, lastindex); 
return(rawname);
}

return("");
}

int main(int argc, char** argv) {

string path = "/home/aymen/hello_world.cpp";
string ss = getFileName(path);
std::cout << "The file name is \"" << ss << "\"\n";
}