我需要将整个文件读入内存,并将其放在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[]。我想避免循环,即我不想:

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()

什么好主意吗?


当前回答

我认为如果没有显式或隐式循环,没有先读入char数组(或其他容器),然后构造字符串,就无法做到这一点。如果不需要字符串的其他功能,可以使用vector<char>,就像当前使用char *一样。

其他回答

试试下面两种方法中的一种:

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
}

更新:事实证明,这种方法虽然很好地遵循了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的方法。看起来你把它和C的fopen搞混了。

编辑:还要注意字符串构造函数的第一个参数周围有额外的圆括号。这些都是必不可少的。它们防止了所谓的“最恼人的解析”问题,在这种情况下,它实际上不会像通常那样给你一个编译错误,但会给你一个有趣的(读作:错误)结果。

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

#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>());

我认为如果没有显式或隐式循环,没有先读入char数组(或其他容器),然后构造字符串,就无法做到这一点。如果不需要字符串的其他功能,可以使用vector<char>,就像当前使用char *一样。

如果你碰巧使用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;
}

我想出了另一种方法,适用于大多数istreams,包括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();
    }
}