使用 Qt 解压 gzip 数据时出错
我正在使用 Qt 的 zlib 库解压缩从 http 服务器接收到的 gzip 数据。因为 qUncompress 不好,所以我遵循此处给出的建议: Qt quncompress gzip data 并创建了我的自己的方法来解压缩 gzip 数据,如下所示:
QByteArray gzipDecompress( QByteArray compressData )
{
//strip header
compressData.remove(0, 10);
const int buffer_size = 16384;
quint8 buffer[buffer_size];
z_stream cmpr_stream;
cmpr_stream.next_in = (unsigned char *)compressData.data();
cmpr_stream.avail_in = compressData.size();
cmpr_stream.total_in = 0;
cmpr_stream.next_out = buffer;
cmpr_stream.avail_out = buffer_size;
cmpr_stream.total_out = 0;
cmpr_stream.zalloc = Z_NULL;
cmpr_stream.zfree = Z_NULL;
cmpr_stream.opaque = Z_NULL;
int status = inflateInit2( &cmpr_stream, -8 );
if (status != Z_OK) {
qDebug() << "cmpr_stream error!";
}
QByteArray uncompressed;
do {
cmpr_stream.next_out = buffer;
cmpr_stream.avail_out = buffer_size;
status = inflate( &cmpr_stream, Z_NO_FLUSH );
if (status == Z_OK || status == Z_STREAM_END)
{
QByteArray chunk = QByteArray::fromRawData((char *)buffer, buffer_size - cmpr_stream.avail_out);
uncompressed.append( chunk );
}
else
{
inflateEnd(&cmpr_stream);
break;
}
if (status == Z_STREAM_END)
{
inflateEnd(&cmpr_stream);
break;
}
}
while (cmpr_stream.avail_out == 0);
return uncompressed;
}
如果解压缩的数据适合输出缓冲区(即小于 16 Kb),那么一切似乎都可以正常工作。如果没有,第二次调用 inflate 将返回 Z_DATA_ERROR。我确信数据是正确的,因为如果输出缓冲区足够大,同一数据块就会正确解压缩。
服务器不会返回未压缩数据大小的标头(仅返回压缩数据的大小),因此我按照 zlib 中的使用说明进行操作: http://www.zlib.net/zlib_how.html
他们所做的正是我正在做的事情。知道我可能会错过什么吗?流中的 next_in 和vail_in 成员似乎在第一次迭代后正确更新。哦,如果有什么用的话,发出数据错误时的错误消息是:“无效距离太远了”。
有什么想法吗?谢谢。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Deflate/Inflate 压缩/解压缩算法使用 32Kb 循环缓冲区。因此,如果解压缩的数据大于 16Kb,则 16Kb 缓冲区将永远无法工作。 (严格来说并不正确,因为允许将数据分割成块,但您需要假设其中可能有 32Kb 块。)因此,只需设置
buffer_size = 32768
就可以了。The Deflate/Inflate compression/decompression algorithm uses a 32Kb circular buffer. So a 16Kb buffer can never work if the decompressed data is bigger than 16Kb. (Not strictly true, because the data is allowed to be split into blocks, but you need to assume that there may be 32Kb blocks in there.) So just set
buffer_size = 32768
and you should be OK.