使用Qt解压缩gzip数据时出错

时间:2011-04-21 08:43:01

标签: qt compression 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),那么Eveything似乎工作正常。如果没有,则第二次调用膨胀返回Z_DATA_ERROR。我确信数据是正确的,因为如果输出缓冲区足够大,则会正确解压缩相同的数据块。

服务器不返回包含未压缩数据大小的标头(仅限压缩文件的大小),因此我按照zlib中的使用说明进行操作:http://www.zlib.net/zlib_how.html

他们正是我正在做的事情。知道我可能错过什么吗?第一次迭代后,流中的next_in和avail_in成员似乎正确更新。哦,如果它有用,发出数据错误时的错误信息是:“无效距离太远”。

有什么想法?感谢。

1 个答案:

答案 0 :(得分:3)

Deflate / Inflate压缩/解压缩算法使用32Kb循环缓冲区。因此,如果解压缩的数据大于16Kb,则16Kb缓冲区永远不会工作。 (不完全正确,因为允许将数据拆分成块,但是你需要假设那里可能有32Kb的块。)所以只需设置buffer_size = 32768就可以了。