为 char 数组调整 zlib zpipe

adapt zlib zpipe for char arrays

我有一个从 .gz 文件中获取的字符数组 (char* dataToInflate) 我想膨胀到另一个字符数组中。

我不知道原始解压缩后的大小,所以我相信这意味着我不能使用 zlib 库中的 uncompress 函数,因为根据手册:

The size of the uncompressed data must have been saved previously by the compressor and transmitted to the decompressor by some mechanism outside the scope of this compression library.

我看过 zpipe.C 示例 (https://zlib.net/zpipe.c),这里的 inf 函数看起来很合适,但我不确定如何将它从 FILE 调整为 char 数组。

有谁知道如何或有任何其他想法将一个 char 数组扩展到另一个 char 数组?

更新:

我在这里阅读:Uncompress() of 'zlib' returns Z_DATA_ERROR

对于通过 gzip 文件获取的数组,uncompress 不适合。

我发现我可以像这样使用 gzopen、gzread 和 gzclose 完全解压缩文件:

    gzFile in_file_gz = gzopen(gz_char_array, "rb");
    char unzip_buffer[8192];
    int unzipped_bytes;
    std::vector<char> unzipped_data;

    while (true) {
        unzipped_bytes = gzread(in_file_gz, unzip_buffer, 8192);
        if (unzipped_bytes > 0) {
            unzipped_data.insert(unzipped_data.end(), unzip_buffer, unzip_buffer + unzipped_bytes);
        } else {
            break;
        }
    }

    gzclose(in_file_gz)

但我也希望能够解压缩 char 数组。我尝试了以下方法:

void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong *uncomprLen) {

    int err;
    z_stream d_stream; /* decompression stream */
    d_stream.zalloc = NULL;
    d_stream.zfree = NULL;
    d_stream.opaque = NULL;
    d_stream.next_in = compr;
    d_stream.avail_in = 0;
    d_stream.next_out = uncompr;
    err = inflateInit2(&d_stream, MAX_WBITS + 16);
    CHECK_ERR(err, "inflateInit");

    while (d_stream.total_out < *uncomprLen && d_stream.total_in < comprLen) {
        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
        err = inflate(&d_stream, Z_NO_FLUSH);
        if (err == Z_STREAM_END)
            break;
        CHECK_ERR(err, "inflate");
    }
    err = inflateEnd(&d_stream);
    *uncomprLen = d_stream.total_out;

}

但是在while循环中,inflate方法returns Z_STREAM_END在文件完全解压之前

方法returns成功,但只写入了部分缓冲区。 我在这里放了一个最小的工作示例: https://github.com/alanjtaylor/zlibExample

如果有人有时间看的话。

非常感谢!

uncompress 确实是为您准备好所有信息而设计的。这是一个效用函数。

可能 包装inflate,这就是您要使用的。您必须 运行 循环并通过重复指向下一个缓冲数据块直到它全部被吃掉来自己管理“流”参数。

an annotated example in the documentation.

您在 github 上的示例,“zippedFile.gz”是七个独立 gzip 成员的串联。这是 gzip 标准 (RFC 1952) 允许的,并且 zlib gz* 文件函数自动处理所有成员。

pigz 将显示所有成员:

% pigz -lvt zippedFile.gz 
method    check    timestamp    compressed   original reduced  name
gzip 8  e323586d  ------ -----      616431    1543643   60.1%  zippedFile
gzip 8  7efd928a  ------ -----      369231     921600   59.9%  <...>
gzip 8  7ebd8b2a  ------ -----      919565    2319970   60.4%  <...>
gzip 8  3dd6e2ba  ------ -----      619670    1549236   60.0%  <...>
gzip 8  c1cb922e  ------ -----      600367    1533151   60.8%  <...>
gzip 8  a9fef06c  ------ -----      620250    1541785   59.8%  <...>
gzip 8  43b57506  ------ -----      623081    1555203   59.9%  <...>

inflate*函数一次只会处理一个成员,为了让你知道Z_STREAM_END成员解压成功,CRC校验正常。

所有你需要做的就是把你的充气机放在一个循环中 运行 它直到输入耗尽,或者你 运行 出错。 (这在 documentation for inflateInit2 in zlib.h 中有注明。)

您的充气机存在一些问题,但我知道这只是初步尝试,所以我不会发表评论。