调用zlib
后,avail_in
对avail_out
inflate
的状态提供了哪些保证?我看到miniz
的特殊行为,我想确保它不是对zlib
API的误解。实际上,在调用inflate
后,我avail_in
非零,avail_out
也非零,因此某些输入看起来没有得到处理。更多细节如下。
我一直在使用miniz来扩充/收缩我流入/流出磁盘的文件。我的膨胀/收缩循环与zpipe.c中的zlib样本相同,包括使用MZ_NO_FLUSH
。
这个循环几乎总是有效,但今天我膨胀了一个早先放气的流并且始终保持MZ_DATA_ERROR
。在添加了正确的标题后,gzip
能够将其充气并且我的数据完好无损。
我的问题的根源归结为对mz_inflate
的最后一次调用。我在这里包括典型的膨胀循环:
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
内部do
循环重复,直到处理完所有当前块并且avail_out
有额外空间。但是,在此特定流的最后一个块上,inflate
未返回错误,而是将avail_in
减少为某个非零数字,并且还会减少avail_out
到某个(其他)非零数字。因此内部do
循环退出,因为avail_out
非零,我们尝试将更多数据导入next_in
和avail_in
,即使不是全部avail_in
已处理1}},因为avail_in
非零。这会破坏next_in
和avail_in
中的任何内容,并且inflate
会在下一次通话中失败。
我的解决方法是从
更改内循环的终止条件strm.avail_out == 0
到
strm.avail_out == 0 || strm.avail_in > 0
但我不知道这是否正确。我觉得这可能是miniz
中的错误,但我不确定。我原以为如果avail_in
表示仍有待处理的数据,则avail_out
必须为零。
如果相关:我使用的输入缓冲区大小为512KB,输出缓冲区为2MB。
答案 0 :(得分:2)
如果inflate()
返回Z_OK
或Z_BUF_ERROR
,而avail_out
不为零,则avail_in
为< / em>零。
您能提供有问题的压缩数据吗?