首页 文章

将整个ASCII文件读入C std :: string [duplicate]

提问于
浏览
514

这个问题在这里已有答案:

我需要将整个文件读入内存并将其放在C std::string 中 .

如果我将其读入 char[] ,答案将非常简单:

std::ifstream t;
int length;
t.open("file.txt");      // open input file
t.seekg(0, std::ios::end);    // go to the end
length = t.tellg();           // report location (this is the length)
t.seekg(0, std::ios::beg);    // go back to the beginning
buffer = new char[length];    // allocate memory for a buffer of appropriate dimension
t.read(buffer, length);       // read the whole file into the buffer
t.close();                    // close file handle

// ... Do stuff with buffer here ...

现在,我想做同样的事情,但使用 std::string 而不是 char[] . 我想避免循环,即我 don't 想要:

std::ifstream t;
t.open("file.txt");
std::string buffer;
std::string line;
while(t){
std::getline(t, line);
// ... Append line to buffer and go on
}
t.close()

有任何想法吗?

9 回答

  • 49

    我认为最好的方法是使用字符串流 . 简单快捷!!!

    ifstream inFile;
    inFile.open(inFileName);//open the input file
    
    stringstream strStream;
    strStream << inFile.rdbuf();//read the file
    string str = strStream.str();//str holds the content of the file
    
    cout << str << endl;//you can do anything with the string!!!
    
  • 11

    尝试以下两种方法之一:

    string get_file_string(){
        std::ifstream ifs("path_to_file");
        return string((std::istreambuf_iterator<char>(ifs)),
                      (std::istreambuf_iterator<char>()));
    }
    
    string get_file_string2(){
        ifstream inFile;
        inFile.open("path_to_file");//open the input file
    
        stringstream strStream;
        strStream << inFile.rdbuf();//read the file
        return strStream.str();//str holds the content of the file
    }
    
  • 678

    有几种可能性 . 我喜欢使用stringstream作为中间人:

    std::ifstream t("file.txt");
    std::stringstream buffer;
    buffer << t.rdbuf();
    

    现在"file.txt"的内容在字符串中显示为 buffer.str() .

    另一种可能性(虽然我当然不喜欢它)更像是你的原创:

    std::ifstream t("file.txt");
    t.seekg(0, std::ios::end);
    size_t size = t.tellg();
    std::string buffer(size, ' ');
    t.seekg(0);
    t.read(&buffer[0], size);
    

    正式地说,这不需要在C 98或03标准下工作(字符串不需要连续存储数据)但事实上它适用于所有已知的实现,而C 11及更高版本确实需要连续存储,因此它保证与他们合作 .

    至于为什么我不喜欢后者:首先,因为它更长,更难阅读 . 其次,因为它要求您使用您不关心的数据初始化字符串的内容,然后立即写入该数据(是的,初始化的时间通常与读数相比是微不足道的,所以它可能无关紧要,但对我来说,它仍然感觉有点不对劲) . 第三,在文本文件中,文件中的位置X并不一定意味着您将读取X字符以达到该点 - 不需要考虑线端翻译之类的内容 . 在进行此类翻译的真实系统(例如,Windows)上,翻译后的表单比文件中的更短(即,文件中的“\ r \ n”在翻译后的字符串中变为“\ n”)所以你所做的一切预留一些你从未使用的额外空间 . 再说一遍,并不是真的会引起重大问题,但无论如何都会感到有点不对劲 .

  • -6

    你可能在任何书籍或网站上都找不到这个,但我发现它运作得很好:

    ifstream ifs ("filename.txt");
    string s;
    getline (ifs, s, (char) ifs.eof());
    
  • 451

    我想出了另一种适用于大多数istream的方法,包括std :: cin!

    std::string readFile()
    {
    stringstream str;
    ifstream stream("Hello_World.txt");
    if(stream.is_open())
    {
        while(stream.peek() != EOF)
        {
            str << (char) stream.get();
        }
        stream.close();
        return str.str();
    }
    }
    
  • 1

    我可以这样做:

    void readfile(const std::string &filepath,std::string &buffer){
        std::ifstream fin(filepath.c_str());
        getline(fin, buffer, char(-1));
        fin.close();
    }
    

    如果这是令人不悦的事情,请告诉我原因

  • 7

    如果您碰巧使用glibmm,可以试试Glib::file_get_contents .

    #include <iostream>
    #include <glibmm.h>
    
    int main() {
        auto filename = "my-file.txt";
        try {
            std::string contents = Glib::file_get_contents(filename);
            std::cout << "File data:\n" << contents << std::endl;
        catch (const Glib::FileError& e) {
            std::cout << "Oops, an error occurred:\n" << e.what() << std::endl;
        }
    
        return 0;
    }
    
  • 2

    我不需要字符串的其他功能,它可以用 vector<char> 完成,就像你当前使用 char * 一样 .

  • 1

    Update: 事实证明,这种方法在遵循STL惯用法的同时实际上效率低得惊人!不要对大文件这样做 . (见:http://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html

    你可以从文件中创建一个streambuf迭代器并用它初始化字符串:

    #include <string>
    #include <fstream>
    #include <streambuf>
    
    std::ifstream t("file.txt");
    std::string str((std::istreambuf_iterator<char>(t)),
                     std::istreambuf_iterator<char>());
    

    不确定从哪里获得 t.open("file.txt", "r") 语法 . 据我所知,这不是 std::ifstream 的方法 . 它看起来像你've confused it with C' s fopen .

    Edit: 还要注意字符串构造函数的第一个参数周围的额外括号 . 这些都很重要 . 它们可以防止称为“most vexing parse”的问题,在这种情况下,它实际上不会像通常那样给你一个编译错误,但会给你带来有趣的(读取:错误的)结果 .

    根据KeithB在评论中的观点,这里有一种方法可以预先分配所有内存(而不是依赖于字符串类的自动重新分配):

    #include <string>
    #include <fstream>
    #include <streambuf>
    
    std::ifstream t("file.txt");
    std::string str;
    
    t.seekg(0, std::ios::end);   
    str.reserve(t.tellg());
    t.seekg(0, std::ios::beg);
    
    str.assign((std::istreambuf_iterator<char>(t)),
                std::istreambuf_iterator<char>());
    

相关问题