Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何将文件内容读入istringstream?_C++_Optimization_Memory_Stream_Stringstream - Fatal编程技术网

C++ 如何将文件内容读入istringstream?

C++ 如何将文件内容读入istringstream?,c++,optimization,memory,stream,stringstream,C++,Optimization,Memory,Stream,Stringstream,为了提高从文件读取的性能,我尝试将一个大文件(数MB)的全部内容读取到内存中,然后使用istringstream访问信息 我的问题是,读取这些信息并将其“导入”到字符串流中的最佳方法是什么?这种方法的一个问题(见下文)是,在创建字符串流时,缓冲区会被复制,内存使用量会加倍 #include <fstream> #include <sstream> using namespace std; int main() { ifstream is; is.open (s

为了提高从文件读取的性能,我尝试将一个大文件(数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
   */

}
#包括
#包括
使用名称空间std;
int main(){
如果流是;
is.open(sFilename.c_str(),ios::binary);
//获取文件的长度:
is.seekg(0,std::ios::end);
长长度=is.tellg();
is.seekg(0,std::ios::beg);
//分配内存:
字符*缓冲区=新字符[长度];
//将数据作为块读取:
is.read(缓冲区、长度);
//创建内存内容的字符串流
//注意:这会复制缓冲区!!!
istringstream iss(字符串(缓冲区));
//删除临时缓冲区
删除[]缓冲区;
//关闭文件流
is.close();
/* ==================================
*使用iss访问数据
*/
}

std::ifstream
有一个方法
rdbuf()
,该方法返回指向
文件buf
的指针。然后,您可以将此
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...
    }
}
#包括
#包括
int main()
{
std::ifstream文件(“myFile”);
如果(文件)
{
std::stringstream缓冲区;

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

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

好的。我不是说这将比从文件

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

注意:值得一提的是,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.
         */
    }
}
#包括
#包括
#包括
int main()
{
std::ifstream文件(“Plop”);
如果(文件)
{
/*
*获取文件的大小
*/
seekg(0,std::ios::end);
std::streampos length=file.tellg();
seekg(0,std::ios::beg);
/*
*使用向量作为缓冲区。
*它是异常安全的,将被正确地整理。
*此构造函数创建正确长度的缓冲区。
*
*然后将整个文件读入缓冲区。
*/
std::向量缓冲区(长度);
读取(&缓冲区[0],长度);
/*
*创建字符串流。
*从流中获取stringbuffer并将向量设置为它的源。
*/
std::stringstream localStream;
localStream.rdbuf()->pubsetbuf(&buffer[0],长度);
/*
*注意,如果缓冲区超出范围,则不会复制它
*流将从释放的内存中读取。
*/
}
}

Hi Luc,我同意你的建议…rdbuf的操作是一个不错的选择!但是你的解决方案不是也有同样的问题吗?你不创建同一缓冲区的两个副本吗,至少是暂时的吗?因为当operatorIt似乎正在删除我需要的新行字符时。is
file.close();
必要吗?@artm这不是强制性的,但最好在使用完文件句柄后立即关闭它们。如果没有对
close
的显式调用,当
file
被销毁时(在其作用域的末尾,因此在
main
的末尾),文件就会被关闭。最好的方法可能是限制
文件的范围。
@Martin York,你是如何了解这些细节的,当你遇到问题时,你是阅读还是研究,然后了解所有这些细节?非常感谢,bdw。@Gollum:不,这只是从两个方面获得的细节。1)一直使用流类。2)拥有实现了我自己的流类。数字(2)使您能够大量阅读流的工作原理,因为您希望流的工作方式与标准流的工作方式相同(这样您就可以对标准流重复使用STL库函数)。上面唯一不完整的一点是修改流缓冲区的工作方式。我不认为“因为char是一种未初始化的POD数据类型”这一点是正确的。构造函数实际上有两个参数,第二个参数是初始化元素的值。它默认为
t()
char()
在我们的例子中,表示0。因此所有元素都应该是0。-1,这个方法(basic_stringbuf::setbuf)是否定义了实现。@ybungalobill:是的。定义的实现不是“未定义”的。也许您应该改为搜索内存映射文件。您喜欢复制数据。1)复制到缓冲区。2)复制到匿名std::string。3)复制到iss。