web-dev-qa-db-ja.com

全体を読む ASCII ファイルをC++のstd :: stringに入れる

ファイル全体をメモリに読み込み、それを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()

何か案は?

535
Escualo

更新: このメソッドは、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と混同したようです。

編集: 文字列コンストラクタの最初の引数を囲む余分な括弧にも注意してください。 これらは必須です。これは、 " most vexing parse "として知られている問題を防ぎます。この場合、通常のように実際にはコンパイルエラーにはなりませんが、興味深い(read:wrong)結果になります。

コメントでの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>());
476
Tyler McHenry

いくつかの可能性があります。仲介者として文字列ストリームを使用したいのですが。

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以降は連続した記憶域を必要としますそれで、彼らと働くことは保証されています。

なぜ私は後者が好きでもないのかということに関して:最初に、それは長くて読むのが難しいからです。 2つ目は、気にしないデータで文字列の内容を初期化してからすぐにそのデータを上書きする必要があるためです(はい、初期化にかかる時間は通常読みに比べて簡単です。しかし、私にはそれはまだ一種の間違っているように感じます。第三に、テキストファイルでは、ファイル内の位置Xは必ずしもその位置に到達するためにX文字を読んだという意味ではありません - 行末翻訳のようなことを考慮に入れる必要はありません。そのような翻訳をする実際のシステム(例えばWindows)では、翻訳された形式はファイルの中のものより短く(すなわち、ファイルの中の "\ r\n"は翻訳された文字列の中で "\ n"になります)あなたが決して使用しない少し余分なスペースを予約されています。繰り返しますが、実際には大きな問題は発生しませんが、とにかく少し違和感があります。

714
Jerry Coffin

最善の方法は文字列ストリームを使うことだと思います。シンプルで素早い!

#include <fstream>
#include <iostream>
#include <sstream> //std::stringstream
main(){
    std::ifstream inFile;
    inFile.open("inFileName"); //open the input file

    std::stringstream strStream;
    strStream << inFile.rdbuf(); //read the file
    std::string str = strStream.str(); //str holds the content of the file

    std::cout << str << std::endl; //you can do anything with the string!!!
}
55
mili

あなたはこれをどの本やサイトでも見つけられないかもしれませんが、私はそれがかなりうまくいくことを見つけました:

ifstream ifs ("filename.txt");
string s;
getline (ifs, s, (char) ifs.eof());
11
Ankit Acharya

次の2つの方法のいずれかを試してください。

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
}
6
madx

私はstd :: cinを含む、ほとんどのistreamに対応する別の方法を考え出しました。

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();
}
}
2
yash101

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;
}
1

私はこのようにすることができます:

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

これが眉をひそめられる何かであるならば、どうか私に知らせてください

1
chunkyguy