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