ZLib GZIP返回Z_BUF_ERROR(-5)

问题描述 投票:0回答:1

我正在使用zlib库(从src编译)来压缩/膨胀gzip / zlib / raw字节。我创建了一个用于解压缩的包装类(Compressor / Decompresser)。我还创建了几个测试用例(GZIP,ZLib,Raw,Auto-Detect)。测试通过了Zlib / Raw / Auto-Detect(Zlib),但没有通过GZip(15u | 16u的窗口位)。

这是我的压缩功能。

    std::vector<char> out(zlib->avail_in + 8);

    deflateInit2(zlib.get(), Z_DEFAULT_COMPRESSION, Z_DEFLATED, static_cast<int32_t>(mode), 8, Z_DEFAULT_STRATEGY);

    zlib->avail_out = out.size();
    zlib->next_out = reinterpret_cast<Bytef*>(out.data());

    deflate(zlib.get(), Z_FINISH);

    out.resize(zlib->total_out + 3);

    deflateEnd(zlib.get());
    return std::move(out);

这里是解压缩

    uIntf multiplier = 2;
    uIntf currentSize = zlib->avail_in * (multiplier++) * 1000 /* Just to make sure enough output space(will implement loop) */;

    std::vector<char> out(currentSize);

    inflateInit2(zlib.get(), static_cast<int>(mode));

    zlib->avail_out = out.size();
    zlib->next_out = reinterpret_cast<Bytef*>(out.data());

    inflate(zlib.get(), Z_FINISH);

    out.resize(zlib->total_out);
    inflateEnd(zlib.get());
    return std::move(out);

Input被设置为另一个函数(正在被调用),看起来像这样。 (调用compress / decompress时不会删除char *)

    zlib->next_in = reinterpret_cast<Bytef*>(bytes);
    zlib->avail_in = static_cast<uIntf>(length);

我也有一个模式枚举

    enum class Mode : int32_t {
        AUTO = 15u | 32u, // Never used on compress
        GZIP = 15u | 16u,
        ZLIB = 15,
        RAW = -15
    };

注:模式为AUTO(与zlib配对),ZLibRAW的测试用例起作用。 GZip无法通过测试用例。 (测试用例只是一个简单的字母数字字符数组)。

还调试了gzip解压缩的输出(失败后,并且输出缺少最后3个字符(y,z,终止字符)]

[另一注:包装器类的构造函数如下所示

    zlib->zalloc = Z_NULL;
    zlib->zfree = Z_NULL;
    zlib->opaque = Z_NULL;
    zlib->avail_in = 0;
    zlib->next_in = Z_NULL;
c++ c gzip zlib deflate
1个回答
1
投票

首先,一堆没有上下文的分散的代码片段使无法看到正在发生的事情。请参见How to create a Minimal, Reproducible Example以获取如何提供一个体面的示例。

第二,您不是说what返回Z_BUF_ERROR。您的代码段中甚至没有保留deflate()inflate()返回值的地方,因此甚至看不到Z_BUF_ERROR!您至少需要执行int ret = deflate(zlib.get(), Z_FINISH);之类的操作,然后检查ret的值。

[第三,我无法在您的代码片段中告诉您设置输入指针和长度的位置或位置。在初始化之前将长度设置为零吗?还是设置为数据?还是在初始化之后设置数据指针和长度?请参阅上面的MRE链接。

第四,我们没有您正在使用的示例数据。因此,我们无法重现该错误。再次,请参阅MRE链接。

[好,所以在这里暗中刺刺,我猜想deflate()正在返回错误。那么问题可能出在您没有提供足够的输出空间,而您要求了Z_FINISH,这告诉deflate()have提供了足够的输出空间。在这种情况下,deflate()返回Z_BUF_ERROR表示您没有。如果数据不可压缩,则压缩可以扩展数据,并且gzip比zlib添加更多的头和尾信息。您的+ 8不足以说明这两件事。 zlib的标头和结尾为6个字节,而gzip的标头和结尾为至少18个字节。扩展是输入的乘数,加上百分比的一部分,在长度上根本没有乘数。

zlib为此提供了一个功能,deflateBound()。您可以在deflateInit()之后用输入的大小调用它,它将返回压缩输出的最大大小。

但是最好在循环中多次调用deflate()。对于大多数实际应用,有必要在一个循环中多次调用inflate()。在您的评论中以及您试图(也不足以)乘以一千来解释膨胀数据的可能大小时,都可以看到这一点。

您可以在zlib Usage Example上找到有关如何正确使用带循环的zlib函数的详细注释示例。

© www.soinside.com 2019 - 2024. All rights reserved.