从"大"开放和阅读g中的gzip压缩文件

时间:2017-11-23 07:19:41

标签: c file io gzip

我一直在尝试使用C中的 gzip-based 文件IO函数打开并读取 gzip 压缩文件。我和我一起使用的压缩文件非常大大小为12 GB。未压缩的文件 ~260 GB ,因此我不准备使用gunzip解压缩文件并从那里继续。

我特意使用以下代码来读取和写入我们可用的缓冲区 -

let g:codi#interpreters = {
  \ 'javascript': {
     \ 'rightalign': 0,
  \ },
\ }

代码根据您最初指定的缓冲区准确地从zlib文件读取和写入。缓冲区大小固定为某个值(在上述情况下为 0x4000 )。

现在的问题是我无法将此缓冲区的大小增加到某个值以上(我可以使用3276008作为缓冲区大小,但不能使用32760008 )。要读取12 GB的压缩值,需要使用非常大的缓冲区。正如我的编辑中所指出的,这看起来像某种#define windowBits 15 #define ENABLE_ZLIB_GZIP 32 #define CHUNK 0x4000 #define CALL_ZLIB(x) { \ int status; \ status = x; \ if (status < 0) \ { \ fprintf(stderr, "%s:%d: %s returned a bad status of %d.\n", __FILE__, __LINE__, #x, status); \ exit(EXIT_FAILURE);\ } \ } \ int main () { const char * file_name = "test.gz"; FILE * file; z_stream strm = {0}; unsigned char in[CHUNK]; unsigned char out[CHUNK]; strm.zalloc = Z_NULL; strm.zfree = Z_NULL; strm.opaque = Z_NULL; strm.next_in = in; strm.avail_in = 0; CALL_ZLIB (inflateInit2 (& strm, windowBits | ENABLE_ZLIB_GZIP)); /* Open the file. */ file = fopen (file_name, "rb"); while (1) { int bytes_read; bytes_read = fread (in, sizeof (char), sizeof (in), file); strm.avail_in = bytes_read; do { unsigned have; strm.avail_out = CHUNK; strm.next_out = out; CALL_ZLIB (inflate (& strm, Z_NO_FLUSH)); have = CHUNK - strm.avail_out; fwrite (out, sizeof (unsigned char), have, stdout); } while (strm.avail_out == 0); if (feof (file)) { inflateEnd (& strm); break; } } return 0; } 而不是DATA_ERROR错误...所以它毕竟不是缓冲区错误!

有什么方法可以使用上面的BUFFER函数记录整个12 GB压缩文件?

编辑#1

函数zlib返回的错误代码由inflate函数封装,我很遗憾未包含该函数。因此,当我使用0x4000的缓冲区大小运行时,我得到以下错误代码。我已将CALL_ZLIB函数添加到代码中供您参考。

错误消息:

CALL_ZLIB。这显然看起来像** DATA_ERROR。

编辑#2

我尝试将一个负值windowBits 添加到InflateInit2(),但这并没有解决我的任何问题。 inflate()函数最初正确读取我的文件 - 以我想要的方式显示我的所有数据..

parser.c:96: inflate(&strm, Z_NO_FLUSH) returned a bad status of -3

但过了一段时间后,显示的输出变得乱码,我再也看不懂了..

0x55b0 [0x40]: event: 3
.
. ... raw event: size 64 bytes
.  0000:  03 00 00 00 00 00 40 00 18 03 00 00 18 03 00 00  ......@.........
.  0010:  4d 6f 64 65 6d 4d 61 6e 61 67 65 72 00 00 00 00  ModemManager....
.  0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
.  0030:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

0 0 0x55b0 [0x40]: PERF_RECORD_COMM: ModemManager:792/792

0x55f0 [0x40]: event: 7
.
. ... raw event: size 64 bytes
.  0000:  07 00 00 00 00 00 40 00 19 03 00 00 01 00 00 00  ......@.........
.  0010:  19 03 00 00 01 00 00 00 00 00 00 00 00 00 00 00  ................
.  0020:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
.  0030:  00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................

0 0 0x55f0 [0x40]: PERF_RECORD_FORK(793:793):(1:1)

0x5630 [0x40]: event: 3
.

这最终终止于我在编辑#1

中描述的错误消息

1 个答案:

答案 0 :(得分:0)

我已经解决了这个问题。

基本问题是我没有在循环内的代码中初始化z_stream的strm.next_in成员。因此,在进行1次迭代后,缓冲区被破坏,我得到了上述错误。

我将代码修改为 -

  strm.next_in = in;
  strm.avail_in = 0;

  CALL_ZLIB(inflateInit2 (&strm, windowBits | ENABLE_ZLIB_GZIP));

  file = fopen(filename, "rb");

  while(1)
  {
    int bytes_read;
    strm.next_in = in;     // added this line

    bytes_read = fread(in, sizeof(char), sizeof(in), file);

    strm.avail_in = bytes_read;

    do
    {
      unsigned have;
      strm.avail_out = CHUNK;
      strm.next_out  = out;