在c ++中有效地阅读大文本

时间:2011-02-01 06:05:10

标签: c++ boost large-files

我必须在C ++中阅读一个大文本文件(> 10 GB)。这是一个具有可变长度行的csv文件。当我尝试使用ifstream逐行读取它但是需要很长时间时,我想这是因为每次我读取它进入磁盘并读取的行时,这会使它非常慢。

有没有办法读取bufferes,例如一次读取250 MB(使用ifstream的读取方法)然后从此缓冲区获取行,我看到像缓冲区这样的解决方案的许多问题可能有不完整的行等。 。

在c ++中是否有解决所有这些情况的解决方案等。是否有任何开源库可以执行此操作,例如boost等?

注意:我想避免使用c stye FILE *指针等。

4 个答案:

答案 0 :(得分:7)

尝试使用Windows内存映射文件功能。这些调用是缓冲的,你可以像处理内存那样处理文件。 memory mapped files

答案 1 :(得分:3)

IOstreams已经按照您的描述使用了缓冲区(尽管通常只有几千字节,而不是几百兆字节)。您可以使用pubsetbuf来使用更大的缓冲区,但我不希望获得任何巨大的收益。 IOstreams的大部分开销都来自其他领域(比如使用虚函数),而不是缺少缓冲。

如果您在Windows上运行此功能,您可以通过编写自己的流缓冲区并让它直接调用CreateFile,传递(例如)FILE_FLAG_SEQUENTIAL_SCAN或{ {1}}。在这种情况下,这些中的任何一个都可能对您的表现有很大帮助。

答案 2 :(得分:3)

如果你想要真正的速度,那么你将不得不停止将行读入std :: string,并开始将char* s用于缓冲区。无论是使用ifstream::read()还是使用内存映射文件读取缓冲区都不太重要,尽管read()有一个缺点,你注意到可能有N条完整的行和缓冲区中的不完整行,并且需要识别(很容易)通过扫描缓冲区的其余部分'\ n'来做到这一点 - 可能是在缓冲区之后放置一个NUL并使用strchr)。您还需要将部分行复制到缓冲区的开头,从文件中读取下一个块,以便从该点继续,并更改读取的最大字符数,使其不会溢出缓冲区。如果你对FILE *感到紧张,我希望你对const char * ....

感到满意

由于出于性能原因而提议这样做,我希望您能够确定这不是您的CSV字段提取等,这是真正的瓶颈。

答案 3 :(得分:1)

我希望这会有所帮助 -

http://www.cppprog.com/boost_doc/doc/html/interprocess/sharedmemorybetweenprocesses.html#interprocess.sharedmemorybetweenprocesses.mapped_file

BTW,你写道“我看到很多问题解决方案,如缓冲区可能有不完整的行等...” - 在这种情况下如何读取250 MB,然后读取char by char,直到你得到分隔符来完成该行。