670

ファイル全体をメモリに読み込み、 C++ に配置する必要がありますstd::string

それを a に読み込むとしたら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()

何か案は?

4

9 に答える 9

973

いくつかの可能性があります。私が好きなものは、仲介者として文字列ストリームを使用します:

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 以降では連続したストレージが必要です。 、そのため、それらで動作することが保証されています。

後者も好きではない理由については、まず、長くて読みにくいからです。第二に、気にしないデータで文字列の内容を初期化する必要があるため、すぐにそのデータを上書きします(はい、初期化する時間は通常、読み取りに比べて些細なことなので、おそらく問題ではありません、しかし、私にはまだちょっと間違っているように感じます)。第 3 に、テキスト ファイルでは、ファイル内の位置 X は、その位置に到達するまでに X 文字を読み取ったことを必ずしも意味しません。行末の変換などを考慮する必要はありません。そのような翻訳を行う実際のシステム (Windows など) では、翻訳された形式はファイル内のものよりも短い (つまり、ファイル内の "\r\n" は、翻訳された文字列では "\n" になる)。ve done は、使用しない少し余分なスペースを予約しています。繰り返しますが、実際には大きな問題を引き起こすわけではありませんが、とにかく少し気分が悪いです.

于 2010-04-08T17:53:26.820 に答える
591

更新:この方法は、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 の指摘に従って、(文字列クラスの自動再割り当てに頼るのではなく) すべてのメモリを前もって割り当てる方法を次に示します。

#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>());
于 2010-04-08T17:23:38.680 に答える
0

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

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

これが眉をひそめるべきものである場合、その理由を教えてください

于 2012-10-22T12:55:00.643 に答える
-5

最初に char 配列 (または他のコンテナー) を読み込んで文字列を構築することなく、明示的または暗黙的なループなしでこれを行うことはできないと思います。文字列の他の機能が必要ない場合は、vector<char>現在使用しているchar *.

于 2010-04-08T17:30:26.380 に答える