zlib inflate 返回缓冲区错误
zlib inflate returning a buffer error
我正在尝试使用 zlib 解压缩一个 zip 文件(不使用任何扩展名或第 3 方)。
最初,src_len 是 48756255,dest_len 是 49209890。
while 循环中的第一遍很好:错误是 Z_OK 并且第二遍开始。在第二遍中,无论我做什么,我都会从 inflate 中得到一个 Z_BUF_ERROR。 stream.total_out 此时是 49034460,所以还有一点剩余,但第二遍的 stream.avail_in 是 0。无论如何,我希望 inflate 给我 Z_STREAM_END。我真的不知道怎么回事,有人可以帮忙吗?
void compression::uncompress2(char* dest, unsigned dest_len, char* src, unsigned src_len) {
TempAllocator ta;
z_stream_s stream = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
stream.next_in = (Bytef*)src;
stream.avail_in = (uInt)src_len;
stream.next_out = (Bytef*)dest;
stream.avail_out = (uInt)dest_len;
stream.zalloc = zalloc;
stream.zfree = zfree;
stream.opaque = &ta;
// no header
int err = inflateInit2(&stream, -MAX_WBITS);
XENSURE(err == Z_OK);
bool done = false;
while (!done) {
stream.next_out = (Bytef*)(dest + stream.total_out);
stream.avail_out = dest_len - stream.total_out;
err = inflate(&stream, Z_SYNC_FLUSH);
if (err == Z_STREAM_END)
done = true;
else if (err != Z_OK) {
break;
}
}
err = inflateEnd(&stream);
XENSURE(err == Z_OK);
}
inflate()
将使用可用输出处理尽可能多的输入。一旦它既不能处理输入也不能产生输出,它将return Z_BUF_ERROR
.
在这种情况下,所有输入都已处理,并且有输出空间可供使用,但未检测到流的结尾。你没有得到 Z_STREAM_END
因为出于某种原因你没有提供完整的 deflate 流。
以下是对您的代码的一些其他评论。您的循环什么都不做,并且在循环中设置 next_out
和 avail_out
什么也不做。您在循环中既没有提供新输入也没有提供新输出 space ,因此循环没有意义。围绕 inflate()
进行循环的唯一目的是提供更多输入,提供更多输出 space,或两者兼而有之。此外,当 inflate()
returns 时,next_out
和 avail_out
被更新到输出缓冲区中的下一个可用位置和那里的可用数量 space。您在循环中设置 next_out
和 avail_out
的语句将它们设置为它们已有的值。
在code with proper loops around inflate()
中,一个Z_BUF_ERROR
没有问题,可以继续处理。尽管如果您希望在下一次调用 inflate()
时得到不同的结果,则必须提供更多输入 and/or 更多输出 space。
不需要用零结构初始化stream
。后面的作业就够了。
我正在尝试使用 zlib 解压缩一个 zip 文件(不使用任何扩展名或第 3 方)。 最初,src_len 是 48756255,dest_len 是 49209890。 while 循环中的第一遍很好:错误是 Z_OK 并且第二遍开始。在第二遍中,无论我做什么,我都会从 inflate 中得到一个 Z_BUF_ERROR。 stream.total_out 此时是 49034460,所以还有一点剩余,但第二遍的 stream.avail_in 是 0。无论如何,我希望 inflate 给我 Z_STREAM_END。我真的不知道怎么回事,有人可以帮忙吗?
void compression::uncompress2(char* dest, unsigned dest_len, char* src, unsigned src_len) {
TempAllocator ta;
z_stream_s stream = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
stream.next_in = (Bytef*)src;
stream.avail_in = (uInt)src_len;
stream.next_out = (Bytef*)dest;
stream.avail_out = (uInt)dest_len;
stream.zalloc = zalloc;
stream.zfree = zfree;
stream.opaque = &ta;
// no header
int err = inflateInit2(&stream, -MAX_WBITS);
XENSURE(err == Z_OK);
bool done = false;
while (!done) {
stream.next_out = (Bytef*)(dest + stream.total_out);
stream.avail_out = dest_len - stream.total_out;
err = inflate(&stream, Z_SYNC_FLUSH);
if (err == Z_STREAM_END)
done = true;
else if (err != Z_OK) {
break;
}
}
err = inflateEnd(&stream);
XENSURE(err == Z_OK);
}
inflate()
将使用可用输出处理尽可能多的输入。一旦它既不能处理输入也不能产生输出,它将return Z_BUF_ERROR
.
在这种情况下,所有输入都已处理,并且有输出空间可供使用,但未检测到流的结尾。你没有得到 Z_STREAM_END
因为出于某种原因你没有提供完整的 deflate 流。
以下是对您的代码的一些其他评论。您的循环什么都不做,并且在循环中设置 next_out
和 avail_out
什么也不做。您在循环中既没有提供新输入也没有提供新输出 space ,因此循环没有意义。围绕 inflate()
进行循环的唯一目的是提供更多输入,提供更多输出 space,或两者兼而有之。此外,当 inflate()
returns 时,next_out
和 avail_out
被更新到输出缓冲区中的下一个可用位置和那里的可用数量 space。您在循环中设置 next_out
和 avail_out
的语句将它们设置为它们已有的值。
在code with proper loops around inflate()
中,一个Z_BUF_ERROR
没有问题,可以继续处理。尽管如果您希望在下一次调用 inflate()
时得到不同的结果,则必须提供更多输入 and/or 更多输出 space。
不需要用零结构初始化stream
。后面的作业就够了。