Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/125.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从C+;中的路径提取文件名和扩展名+;_C++_String_File Io - Fatal编程技术网

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

C++ 如何从C+;中的路径提取文件名和扩展名+;,c++,string,file-io,C++,String,File Io,我有一个文件列表存储在.log中,语法如下: c:\foto\foto2003\shadow.gif D:\etc\mom.jpg 我想从这个文件中提取名称和扩展名。你能举一个简单方法的例子吗?不是代码,而是想法: 从输入流(std::ifstream)读取std::string),读取的每个实例都将是完整路径 在\ 从这个位置提取一个子字符串到最后,这将为您提供文件名 对执行查找中的最后一个,两边的子字符串将为您提供名称+扩展名 如果您想要一种安全的方式(即在平台之间可移植,并且不将假设放在

我有一个文件列表存储在
.log
中,语法如下:

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

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

不是代码,而是想法:

  • 从输入流(
    std::ifstream
    )读取
    std::string
    ),读取的每个实例都将是完整路径
  • \
  • 从这个位置提取一个子字符串到最后,这将为您提供文件名
  • 执行
    查找
    中的最后一个,两边的子字符串将为您提供名称+扩展名
  • 如果您想要一种安全的方式(即在平台之间可移植,并且不将假设放在路径上),我建议使用
    boost::filesystem

    它看起来像这样:

    boost::filesystem::path my_path( filename );
    
    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  = "";
        }
    }
    
    然后可以从该路径提取各种数据


    顺便说一句:还要记住,为了使用类似路径的

    c:\foto\foto2003\shadow.gif
    
    您需要以字符串文字形式转义
    \

    const char* filename = "c:\\foto\\foto2003\\shadow.gif";
    
    或者改用
    /

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

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

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

    大概是这样的:

    boost::filesystem::path my_path( filename );
    
    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  = "";
        }
    }
    

    要提取不带扩展名的文件名,请使用boost::filesystem::path::stem而不是难看的std::string::find_last_of(“.”)

    boost::filesystem::path p(“c:/dir/dir/file.ext”);
    
    std::cout我还使用此代码段确定适当的斜杠字符:

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

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

    对于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"
    
    如果需要,您可以通过
    p.filename().string()
    std::filesystem::path
    转换为
    std::string
    ,例如:

    filename and extension: file.ext
    

    对于linux或unix机器,操作系统有两个处理路径和文件名的函数。使用man 3 basename可以获得有关这些函数的更多信息。 使用系统提供的功能的优点是,您不必安装boost或编写自己的功能

    #include <libgen.h>
           char *dirname(char *path);
           char *basename(char *path);
    

    由于BaseNeMe()函数的非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不是很好的样式。我本来可以试试看的
    阻止,以防两次呼叫之间发生问题

    Nickolay Merkin和Yuchen Zhong的回答很好,但从评论中你可以看出,这并不完全准确

    打印时隐式转换为std::string将文件名包装在引号中。这些评论也不准确


    path::filename()
    path::stem()
    返回一个新的路径对象和
    path::string()
    返回对字符串的引用。因此,如 STD::CUT

    尝试以下技巧,从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";
    }
    
    #包括
    #包括
    使用std::string;
    字符串getFileName(常量字符串&s){
    char sep='/';
    #ifdef_WIN32
    sep=“\\”;
    #恩迪夫
    尺寸=s.rfind(sep,s.length());
    if(i!=string::npos)
    {
    字符串文件名=s.substr(i+1,s.length()-i);
    size\u t lastindex=filename.find\u last\u of(“.”);
    字符串rawname=filename.substr(0,lastindex);
    报税表(姓名);
    }
    返回(“”);
    }
    int main(int argc,字符**argv){
    字符串路径=“/home/aymen/hello_world.cpp”;
    字符串ss=getFileName(路径);
    
    std::cout和-1表示不可移植:)为什么投票反对?如果我说的有什么问题,请告诉我,我会解决!@Kos,这太苛刻了!它符合OP的要求,文件基于windows,没有可移植性要求!至少,一个有效的windows路径可以将目录用
    /
    分隔为嗯。我甚至不知道在路径规范中是否存在更多的警告,所以我的想法很简单——如果有一个好的库可以满足我的需要,我应该使用它,因为它可能会比我更好地实现我的目标。;@Nim,但不是有一个
    boost::昆虫::disperser
    通用模板吗?:)+1肯定没有主站点上的示例提供了一种搜索目录的方法:使用path.extension()方法搜索日志(请参阅)事实上,这是大多数情况下的方法,但是它涉及到在某些情况下添加对外部库的不期望的依赖。如果您只想处理C++标准所提供的内容,我建议查看C++正则表达式,在这里您可以定义正则表达式来完成您想要的(在因特网上有很多例子)。。优点-由于一些额外的依赖项而没有开销。但是,这也留下了一个问题-是否需要多平台?Boost会处理路径样式,无论您使用的是Windows还是Linux。使用正则表达式,您必须自己完成。不想成为聪明的傻瓜,但它应该是path.substr而不是path.substring,对吗?同意。最简洁地回答了这个问题。事实上,p.filename()的类型是path,隐式转换时会被引号包围,因此您将得到:filename和扩展名:“file.ext”您可能需要p.filename().string()相反,在C++14/C++17中,你可以使用
    std::experimental::filesystem
    resp
    std::filesystem
    。请参阅下面钟宇晨的帖子。询问者想要一个简单的方法。仅为这个功能向项目添加boost不是一个简单的方法。std::filesystem是一个简单的方法。包括C++17
    #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";
    }