如何将文件内容读入istringstream?

时间:2008-09-25 09:42:12

标签: c++ optimization memory stream stringstream

为了提高从文件读取的性能,我试图将大(几MB)文件的整个内容读入内存,然后使用istringstream来访问信息。

我的问题是,哪个是读取此信息并将其“导入”到字符串流中的最佳方法?这种方法的一个问题(见下文)是在创建字符串流时,缓冲区被复制,内存使用量翻倍。

#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 个答案:

答案 0 :(得分:41)

行。我并不是说这比阅读文件

更快

但是这是一种创建缓冲区的方法,在将数据读入缓冲区后,将其直接用作stringstream的源。

N.B。值得一提的是,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.
         */
    }
}

答案 1 :(得分:39)

std::ifstream有一个方法rdbuf(),它返回一个指向filebuf的指针。然后,您可以将此filebuf“推送”到stringstream

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

    if ( file )
    {
        std::stringstream buffer;

        buffer << file.rdbuf();

        file.close();

        // operations on the buffer...
    }
}
编辑:正如Martin York在评论中所说的那样,这可能不是最快的解决方案,因为stringstream operator<<将逐个字符地读取filebuf。您可能想要检查他的答案,他在那里使用ifstream的{​​{1}}方法,然后将read缓冲区设置为指向先前分配的内存。 / p>

答案 2 :(得分:1)

这对我来说似乎是不成熟的优化。在处理过程中完成了多少工作。假设现代化的桌面/服务器而不是嵌入式系统,在初始化期间复制几MB数据相当便宜,特别是与首先从磁盘读取文件相比。我会坚持你所拥有的,在完成后测量系统,并决定潜在的性能提升是否值得。当然,如果内存紧张,这是一个内循环,或经常被调用的程序(如每秒一次),它会改变平衡。

答案 3 :(得分:0)

要记住的另一件事是文件I / O总是最慢的操作。 Luc Touraille的解决方案是正确的,但还有其他选择。一次将整个文件读入内存将比单独读取快得多。