我有一些.gz压缩文件,大约5-7gig未压缩.这些是flatfiles.
我编写了一个程序,它接受一个未压缩的文件,并按行读取它,这非常有效.
现在我希望能够在内存中打开压缩文件并运行我的小程序.
我看过zlib但我找不到一个好的解决方案.
由于32位无符号int限制,使用gzread(gzFile,void*,unsigned)加载整个文件是不可能的.
我已经尝试了gzgets,但这几乎是执行时间的两倍,而不是使用gzread读取.(我在2gig样本上测试过.)
我还研究了"缓冲",例如将gzread进程拆分为多个2gig块,使用strcchr找到最后一个换行符,然后设置gzseek.但gzseek将模拟一个完整的文件解压缩.这很慢.
我没有看到任何理智的解决方案.我总是可以做一些检查,无论当前行是否实际上有一个换行符(应该只出现在最后一个部分读取的行中),然后从程序中发生这种情况的点读取更多数据.但这可能会非常难看.
无论如何有任何建议吗?
谢谢
编辑:我不需要同时拥有整个文件,一次只需要一行,但我有一台相当庞大的机器,所以如果这是最简单的我就没有问题.
对于那些建议管道标准输入的人来说,与打开文件相比,我经历了极端的减速.这是我几个月前制作的一个小代码片段,它说明了这一点.
time ./a.out 59846/59846.txt # 59846/59846.txt 18255221 real 0m4.321s user 0m2.884s sys 0m1.424s time ./a.out <59846/59846.txt 18255221 real 1m56.544s user 1m55.043s sys 0m1.512s
和源代码
#include#include #define LENS 10000 int main(int argc, char **argv){ std::istream *pFile; if(argc==2)//ifargument supplied pFile = new std::ifstream(argv[1],std::ios::in); else //if we want to use stdin pFile = &std::cin; char line[LENS]; if(argc==2) //if we are using a filename, print it. printf("#\t%s\n",argv[1]); if(!pFile){ printf("Do you have permission to open file?\n"); return 0; } int numRow=0; while(!pFile->eof()) { numRow++; pFile->getline(line,LENS); } if(argc==2) delete pFile; printf("%d\n",numRow); return 0; }
谢谢你的回复,我还在等着金苹果
edit2:使用cstyle FILE指针而不是c ++流要快得多.所以我认为这是要走的路.
感谢您的所有意见
gzip -cd compressed.gz | yourprogram
然后继续从stdin逐行读取它,因为它是未压缩的.
编辑:回应您对性能的评论.你说直接读取STDIN比直接读取未压缩文件要慢.不同之处在于缓冲.通常,只要输出可用,管道就会产生STDIN(没有或非常小的缓冲).您可以从STDIN执行"缓冲块读取"并自行解析读取块以获得性能.
通过使用gzread()
,您可以获得相同的结果,并可能获得更好的性能.(读取一大块,解析块,读取下一个块,重复)
gzread只读取文件的块,你可以像使用普通的read()调用一样循环它.
你需要将整个文件读入内存吗?
如果你需要的是读取行,你可以将一个相当大的块(比如8192个字节)gzread()放入缓冲区,遍历该缓冲区并找到所有'\n'个字符并将它们作为单独的行处理.您必须保存最后一块,只有一行的一部分,并将其添加到您下次读取的数据中.
您也可以从stdin读取并调用您的应用程序
zcat bigfile.gz | ./yourprogram
在这种情况下,你可以在stdin上使用fgets和类似的东西.这也是有益的,因为你在一个处理器上运行解压缩并在另一个处理器上处理数据:-)