如何使用 ZLIB deflate 方法?
How to use ZLIB deflate method?
我正在尝试使用 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 有点解决了这个问题,但不是很清楚,而且它很旧..
有人能指出我的问题吗?
你应该再读一遍那个页面。这次仔细多了。
您没有在开始时正确设置 avail_in
,并且您没有在环形。你唯一做对的事情就是你认为错误的事情,即计算要写出多少字节。你所拥有的甚至不会“有点工作”。
首先,avail_in
必须始终设置为 next_in
处的可用输入量。因此得名 avail_in
。您将其设置为 CHUNKSIZE
并调用 inflateInit()
,即使该缓冲区中 没有可用的输入 。
然后你把数据读入输入缓冲区后,你就忽略了nr
!您需要将 avail_in
设置为 nr
,以指示缓冲区中实际 的数据量。可能小于 CHUNKSIZE
.
如果您已经处理了上次读取的所有数据(由 avail_in
表示为零),您应该将数据读入输入缓冲区 只有 。
当 deflate()
的调用在循环内完成时,它已更新 next_in
、avail_in
、next_out
和 avail_out
。要再次使用 inbuf
和 outbuf
缓冲区,您需要将 next_in
、next_out
和 avail_out
的值重置为您最初设置的值。 avail_in
将设置在 nr
循环的顶部。
您每次都在用 Z_FINISH
呼叫 deflate()
!其工作方式是您使用 Z_NO_FLUSH
调用 deflate()
直到提供最后一个输入,然后 然后 使用 Z_FINISH
,让它知道完成。 (这就是它被称为那个的原因。)
您的循环将提前退出,因为您需要完成压缩和写入输出,而不仅仅是完成读取输入。
您没有检查 deflate()
的 return 代码。 始终 检查 return 代码。这就是他们在那里的原因。
祝你好运。
我正在尝试使用 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 有点解决了这个问题,但不是很清楚,而且它很旧..
有人能指出我的问题吗?
你应该再读一遍那个页面。这次仔细多了。
您没有在开始时正确设置 avail_in
,并且您没有在环形。你唯一做对的事情就是你认为错误的事情,即计算要写出多少字节。你所拥有的甚至不会“有点工作”。
首先,avail_in
必须始终设置为 next_in
处的可用输入量。因此得名 avail_in
。您将其设置为 CHUNKSIZE
并调用 inflateInit()
,即使该缓冲区中 没有可用的输入 。
然后你把数据读入输入缓冲区后,你就忽略了nr
!您需要将 avail_in
设置为 nr
,以指示缓冲区中实际 的数据量。可能小于 CHUNKSIZE
.
如果您已经处理了上次读取的所有数据(由 avail_in
表示为零),您应该将数据读入输入缓冲区 只有 。
当 deflate()
的调用在循环内完成时,它已更新 next_in
、avail_in
、next_out
和 avail_out
。要再次使用 inbuf
和 outbuf
缓冲区,您需要将 next_in
、next_out
和 avail_out
的值重置为您最初设置的值。 avail_in
将设置在 nr
循环的顶部。
您每次都在用 Z_FINISH
呼叫 deflate()
!其工作方式是您使用 Z_NO_FLUSH
调用 deflate()
直到提供最后一个输入,然后 然后 使用 Z_FINISH
,让它知道完成。 (这就是它被称为那个的原因。)
您的循环将提前退出,因为您需要完成压缩和写入输出,而不仅仅是完成读取输入。
您没有检查 deflate()
的 return 代码。 始终 检查 return 代码。这就是他们在那里的原因。
祝你好运。