【问题标题】:How to use ZLIB deflate method?如何使用 ZLIB 放气方法?
【发布时间】:2020-10-26 18:04:51
【问题描述】:

我正在尝试使用 zlib 来压缩文本文件。它似乎有点工作,除了我很确定我计算写入输出的字节数是错误的。我的代码(由http://zlib.net/zlib_how.html 指导)如下:

int
deflateFile(
  char *infile,
  char *outfile)
{
    #define CHUNKSIZE 1000
    int n,nr,nw,towrite;
    z_stream strm;
    FILE *fin,*fout;
    BYTE *inbuf,*outbuf;
    int ntot=0;

    printf( "Start doDeflateFile:\n" );

    // ALLOC BUFFERS
    inbuf  = malloc( CHUNKSIZE+1 );
    outbuf = malloc( CHUNKSIZE+1 );

    // OPEN FILES
    fin  = fopen( infile,  "rb" );
    fout = fopen( outfile, "wb" );
    
    // SETUP Z STREAM
    strm.zalloc    = Z_NULL;
    strm.zfree     = Z_NULL;
    strm.opaque    = Z_NULL;    
    strm.avail_in  = CHUNKSIZE; // size of input
    strm.next_in   = inbuf;     // input buffer
    strm.avail_out = CHUNKSIZE; // size of output
    strm.next_out  = outbuf;    // output buffer
    
    deflateInit( &strm, Z_BEST_COMPRESSION );   // init stream level
      
    while( TRUE ) {         // loop til EOF on input file
      // READ NEXT INPUT CHUNK
      nr = fread( inbuf, 1, CHUNKSIZE, fin );
      if( nr <= 0 ) {
        printf( "End of input\n" );
        break;
      }
      printf( "\nread  chunk of  %6d bytes\n", nr );

      printf( "calling deflate...\n" );
      n = deflate(&strm, Z_FINISH);             // call ZLIB deflate

      towrite = CHUNKSIZE - strm.avail_out;     // calc # bytes to write (FIXME???)
      printf( "#bytes to write %6d bytes\n", towrite );
      nw = fwrite( outbuf, 1, towrite, fout );
      if( nw != towrite ) break;
      printf( "wrote chunk of  %6d bytes\n", nw );
      ntot += nw;
    }
        
    deflateEnd(&strm);              // end deflate

    printf( "wrote total of %d bytes\n", ntot );
    printf( "End deflateFile.\n" );

    return( 0 );
}

CHUNKSIZE 为 1000 的 1010 字节输入文件的输出是:

 Start deflateFile:

read  chunk of    1000 bytes
calling deflate...
#bytes to write    200 bytes
wrote chunk of     200 bytes

read  chunk of      10 bytes
calling deflate...
#bytes to write    200 bytes
wrote chunk of     200 bytes
End of input
wrote total of 400 bytes

End deflateFile.

SO #4538586 解决了这个问题,但还没有完全解决,而且它已经很老了..
有人能指出我的问题吗?

【问题讨论】:

    标签: compression zlib


    【解决方案1】:

    您应该再次阅读该页面。这次要小心得多。

    您没有在开始时正确设置avail_in,并且您没有在循环中重置next_inavail_innext_outavail_out。唯一正确的是您认为错误的事情,即计算要写出的字节数。你所拥有的甚至不会“有点工作”。

    首先,avail_in 必须始终设置为next_in 处的可用输入量。因此名称为avail_in。您将其设置为CHUNKSIZE 并调用inflateInit(),即使该缓冲区中还没有可用的输入

    然后在将数据读入输入缓冲区后,您将忽略nr!您需要将avail_in 设置为nr,以指示缓冲区中实际 的数据量。它可能小于CHUNKSIZE

    只有在处理完上次读取时存在的所有数据(avail_in 为零)时,才应将数据读入输入缓冲区。

    当在循环内完成对deflate() 的调用时,它会更新next_inavail_innext_outavail_out。要再次使用inbufoutbuf 缓冲区,您需要将next_innext_outavail_out 的值重置为您最初所做的值。 avail_in 将从nr 设置在循环的顶部。

    您每次都用Z_FINISH 打电话给deflate()!它的工作方式是你用Z_NO_FLUSH 调用deflate(),直到提供最后一个输入,然后然后你使用Z_FINISH,让它知道完成。 (这就是它被称为的原因。)

    您的循环将提前退出,因为您需要完成压缩和写入输出,而不仅仅是完成读取输入。

    您没有检查deflate() 的返回码。 总是检查返回码。这就是他们在那里的原因。

    祝你好运。

    【讨论】:

    • 我读了文档,直到我的眼睛流血,但我就是看不懂。但是由于您出色而明确的建议,我得到了它的工作。我会在清理后发布我更正的代码。
    猜你喜欢
    • 2010-12-10
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-04
    • 1970-01-01
    • 2016-10-23
    • 2014-08-22
    相关资源
    最近更新 更多