【问题标题】:Error decompressing gzip data using Qt使用 Qt 解压 gzip 数据时出错
【发布时间】:2011-04-21 08:43:00
【问题描述】:

我正在使用 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 和avail_in 成员似乎在第一次迭代后正确更新。哦,如果有用的话,发出数据错误时的错误消息是:“invalid distance too far back”。

有什么想法吗?谢谢。

【问题讨论】:

    标签: qt compression gzip


    【解决方案1】:

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

    【讨论】:

    • 我有同样的问题,我用下面的方法解决了这个问题试试这个
    猜你喜欢
    • 1970-01-01
    • 2014-01-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-01
    • 1970-01-01
    • 2014-10-21
    • 2012-06-26
    相关资源
    最近更新 更多