我正在使用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),那么Eveything似乎工作正常。如果没有,则第二次调用膨胀返回Z_DATA_ERROR。我确信数据是正确的,因为如果输出缓冲区足够大,则会正确解压缩相同的数据块。
服务器不返回包含未压缩数据大小的标头(仅限压缩文件的大小),因此我按照zlib中的使用说明进行操作:http://www.zlib.net/zlib_how.html
他们正是我正在做的事情。知道我可能错过什么吗?第一次迭代后,流中的next_in和avail_in成员似乎正确更新。哦,如果它有用,发出数据错误时的错误信息是:“无效距离太远”。
有什么想法?感谢。
答案 0 :(得分:3)
Deflate / Inflate压缩/解压缩算法使用32Kb循环缓冲区。因此,如果解压缩的数据大于16Kb,则16Kb缓冲区永远不会工作。 (不完全正确,因为允许将数据拆分成块,但是你需要假设那里可能有32Kb的块。)所以只需设置buffer_size = 32768
就可以了。