10

ファイルを文字列に読み込みたいのですが。私はそれを効率的に行うためのさまざまな方法を探しています。

固定サイズの*charバッファーを使用する

Tonyから、16 kbのバッファーを作成し、そのバッファーを読み取り、読み取るものがなくなるまでバッファーを追加するという回答を受け取りました。私はそれがどのように機能するかを理解していて、それを非常に速く見つけました。私が理解していないのは、その回答のコメントでは、この方法ですべてを2回コピーすると言われているということです。しかし、私が理解しているように、それはディスクからではなく、メモリ内でのみ発生するため、ほとんど気付かれません。バッファからメモリ内の文字列にコピーするのは問題ですか?

istreambuf_iteratorを使用する

私が受け取った他の答えはistreambuf_iteratorを使用しています。コードは美しく最小限に見えますが、非常に低速です。なぜそれが起こるのか分かりません。なぜそれらのイテレータはとても遅いのですか?

memcpy()の使用

この質問に対して、 memcpy()は最速のネイティブメソッドであるため、使用する必要があるというコメントを受け取りました。しかし、文字列とifstreamオブジェクトでmemcpy()を使用するにはどうすればよいですか?ifstreamは独自の読み取り関数で動作するはずではありませんか?memcpy()を使用すると移植性が損なわれるのはなぜですか?VS2010およびGCCと互換性のあるソリューションを探しています。memcpy()がそれらで機能しないのはなぜですか?

+他に可能な効率的な方法はありますか?

10 MB未満の小さなバイナリファイルには、何をお勧めしますか、どのシェルを使用しますか?

(ifstreamを文字列に読み取る方法の違いの比較に興味があるので、この質問を部分的に分割したくありませんでした)

4

2 に答える 2

10

ディスクからではなく、メモリ内でのみ発生するため、ほとんど気付かれません

それは確かに正しいです。それでも、それを行わないソリューションの方が速い場合があります。

なぜそれらのイテレータはとても遅いのですか?

コードは、イテレータが原因ではなく、文字列が割り当てるメモリの量を認識していないために低速です。sはistreambuf_iterator1回しかトラバースできないため、文字列は基本的に繰り返し連結を実行するように強制され、結果としてメモリの再割り当てが発生します。これは非常に低速です。

私のお気に入りのワンライナーは、別の答えから、基になるバッファーから直接ストリーミングすることです。

string str(static_cast<stringstream const&>(stringstream() << in.rdbuf()).str());

最近のプラットフォームでは、これは実際にバッファを事前に割り当てます。ただし、それでも冗長コピーが発生します(からstringstream最後の文字列まで)。

于 2011-06-28T18:13:06.650 に答える
4

最も一般的な方法は、おそらく istreambuf_iterator:を使用した応答です。

std::string s( (std::istreambuf_iterator<char>( source )),
               (std::istreambuf_iterator<char>()) );

正確なパフォーマンスは実装に大きく依存しますが、これが最速のソリューションである可能性はほとんどありません。

興味深い代替案は次のとおりです。

std::istringstream tmp;
tmp << source.rdbuf();
std::string s( tmp.str() );

実装が使用しているものに対して、そしてそれが。内の文字列をどのように成長させるかについて うまく機能している場合、これは非常に迅速になる可能性があります。ただし、以前の実装のいくつか(そしておそらく最近の実装も同様)は、これが非常に悪かったです。 operator<<istringstream

一般に、を使用したパフォーマンスstd::stringは、実装が文字列を成長させるのにどれだけ効率的かによって異なります。実装では、最初にどれだけ大きくするかを決定できません。std::vector<char> の代わりに同じコードを使用して最初のアルゴリズムを比較するか、またはstd::stringを使用して最大サイズを適切に見積もることができる場合は、次のreserveようになります。

std::string s( expectedSize, '\0' );
std::copy( std::istreambuf_iterator<char>( source ),
           std::istreambuf_iterator<char>(),
           s.begin() );

memcpyファイルから読み取ることはできず、優れたコンパイラでは、std::copy(同じデータ型で)使用するほど高速ではありません。

<<私は上記の2番目の解決策をonで 使用する傾向がありますがrdbuf()、これは部分的に歴史的な理由によるものです。istrstreamSTLが標準ライブラリに追加される前に、これを(を使用して)行うことに慣れました。さらに言えば、事前に割り当てられたバッファを試して istrstreamみることをお勧めします(バッファに適切なサイズを見つけることができると仮定します)。

于 2011-06-28T18:11:55.287 に答える