41

ファイルからの読み取りのパフォーマンスを向上させるために、大きな (数 MB) ファイルの内容全体をメモリに読み込んでから、istringstream を使用して情報にアクセスしようとしています。

私の質問は、この情報を読み取って文字列ストリームに「インポート」する最良の方法はどれですか? このアプローチの問題 (以下を参照) は、文字列ストリームを作成するときにバッファがコピーされ、メモリ使用量が 2 倍になることです。

#include <fstream>
#include <sstream>

using namespace std;

int main() {
  ifstream is;
  is.open (sFilename.c_str(), ios::binary );

  // get length of file:
  is.seekg (0, std::ios::end);
  long length = is.tellg();
  is.seekg (0, std::ios::beg);

  // allocate memory:
  char *buffer = new char [length];

  // read data as a block:
  is.read (buffer,length);

  // create string stream of memory contents
  // NOTE: this ends up copying the buffer!!!
  istringstream iss( string( buffer ) );

  // delete temporary buffer
  delete [] buffer;

  // close filestream
  is.close();

  /* ==================================
   * Use iss to access data
   */

}
4

3 に答える 3

53

std::ifstreamrdbuf()へのポインタを返すメソッドがありますfilebuf。次に、これを次のように「プッシュ」できfilebufますstringstream

#include <fstream>
#include <sstream>

int main()
{
    std::ifstream file( "myFile" );

    if ( file )
    {
        std::stringstream buffer;

        buffer << file.rdbuf();

        file.close();

        // operations on the buffer...
    }
}

編集: Martin York がコメントで述べているように、これは最速のソリューションではない可能性がありstringstreamますoperator<<。彼の答えを確認したい場合があります。彼は、以前と同じようにifstream'sreadメソッドを使用してstringstreamから、以前に割り当てられたメモリを指すようにバッファーを設定します。

于 2008-09-25T09:52:08.000 に答える
43

わかった。これがファイルから読み取るよりも速いと言っているわけではありません

ただし、これはバッファを一度作成し、データがバッファに読み込まれた後、それを文字列ストリームのソースとして直接使用する方法です。

注意std::ifstream がバッファリングされることに注意してください。(比較的大きな) チャンクでファイルからデータを読み取ります。ストリーム操作はバッファに対してのみ実行され、さらにデータが必要な場合に別の読み取りのためにファイルに戻ります。したがって、すべてのデータをメモリに吸い込む前に、これがボトルネックであることを確認してください。

#include <fstream>
#include <sstream>
#include <vector>

int main()
{
    std::ifstream       file("Plop");
    if (file)
    {
        /*
         * Get the size of the file
         */
        file.seekg(0,std::ios::end);
        std::streampos          length = file.tellg();
        file.seekg(0,std::ios::beg);

        /*
         * Use a vector as the buffer.
         * It is exception safe and will be tidied up correctly.
         * This constructor creates a buffer of the correct length.
         *
         * Then read the whole file into the buffer.
         */
        std::vector<char>       buffer(length);
        file.read(&buffer[0],length);

        /*
         * Create your string stream.
         * Get the stringbuffer from the stream and set the vector as it source.
         */
        std::stringstream       localStream;
        localStream.rdbuf()->pubsetbuf(&buffer[0],length);

        /*
         * Note the buffer is NOT copied, if it goes out of scope
         * the stream will be reading from released memory.
         */
    }
}
于 2008-09-26T10:29:20.103 に答える
1

これは時期尚早の最適化のように思えます。処理中の作業量。組み込みシステムではなく、最新のデスクトップ/サーバーを想定すると、初期化中に数 MB のデータをコピーするのは、特に最初にディスクからファイルを読み取る場合と比較して、かなり安価です。私はあなたが持っているものに固執し、システムが完成したら測定し、潜在的なパフォーマンスの向上がそれだけの価値があるかどうかを判断します. もちろん、メモリが不足している場合、これは内側のループ、または頻繁に呼び出されるプログラム (1 秒に 1 回など) にあり、バランスが変化します。

于 2008-09-25T12:52:24.977 に答える