Compression 如何使用ZLIB deflate方法?

Compression 如何使用ZLIB deflate方法?,compression,zlib,Compression,Zlib,我正在尝试使用zlib压缩文本文件。这似乎是一种工作,除了我很确定我的计算字节数写入输出是错误的。我的代码(指南)如下: 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;

我正在尝试使用zlib压缩文本文件。这似乎是一种工作,除了我很确定我的计算字节数写入输出是错误的。我的代码(指南)如下:

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 );
}
因此#4538586在某种程度上解决了这个问题,但不完全解决,而且它非常古老。

有人能指出我的问题吗?

你应该再读一遍那一页。这次要小心得多

您没有在开始时正确设置
avail\u in
,也没有在循环中重置
next\u in
avail\u in
next\u out
,以及
avail\u out
。唯一正确的是你认为错误的地方,那就是计算要写多少字节。你所拥有的甚至不会“起作用”

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

然后将数据读入输入缓冲区后,忽略
nr
!您需要将
avail\u in
设置为
nr
,以指示缓冲区中实际有多少数据。它可能小于
CHUNKSIZE

只有在处理了上次读取时的所有数据后,才应将数据读入输入缓冲区,如
中的
avail\u为零所示

deflate()
调用在循环内完成时,它已更新
next\u in
avail\u in
next\u out
avail\u out
。要再次使用
inbuf
extuf
缓冲区,您需要将
next\u in
next\u out
avail\u out
的值重置为最初设置的值<将在循环顶部从
nr
设置code>avail\u in

您每次都在用
Z_FINISH
调用
deflate()
!其工作方式是使用
Z_NO_FLUSH
调用
deflate()
,直到提供最后一个输入,然后使用
Z_FINISH
,让它知道如何完成。(这就是为什么这么叫的原因。)

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

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


祝你好运。

我读了医生的书,直到我的眼睛流血,但我就是看不懂。但多亏了你出色而清晰的建议,我才使它发挥了作用。我会在清理完我的更正代码后发布它。
 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.