如何使用miniz创建可以gzip解压的压缩文件?

Wen*_*ieh 5 c++ gzip miniz

我正在 Windows 平台上用 C++ 编写程序。我想压缩一些存储在char[]数组中的数据,并将其输出到一个文件,稍后我将文件上传到unix服务器,我希望它可以通过gzip -d.

经过大量研究,我选择了miniz。另外,我在这里找到了 gzip 文件格式。

下面是创建 gzip 文件的代码片段:(抱歉我没有放一些变量的定义;它们是在其他地方定义的)

unsigned long zsize;
zpkg[0] = 0x1F;
zpkg[1] = 0x8B;
zpkg[2] = 8;
zpkg[3] = 0;
zpkg[4] = 0;
zpkg[5] = 0;
zpkg[6] = 0;
zpkg[7] = 0;
zpkg[8] = 0;
zpkg[9] = 0xFF;
compress2(zpkg + 10, &zsize, pkg, pkgSize, MZ_DEFAULT_LEVEL);
int footerStart = (int)zsize + 10;
mz_ulong crc = mz_crc32(MZ_CRC32_INIT, zpkg + 10, zsize);
zpkg[footerStart] = crc & 0xFF;
zpkg[footerStart + 1] = (crc >> 8) & 0xFF;
zpkg[footerStart + 2] = (crc >> 16) & 0xFF;
zpkg[footerStart + 3] = (crc >> 24) & 0xFF;
zpkg[footerStart + 4] = pkgSize & 0xFF;
zpkg[footerStart + 5] = (pkgSize >> 8) & 0xFF;
zpkg[footerStart + 6] = (pkgSize >> 16) & 0xFF;
zpkg[footerStart + 7] = (pkgSize >> 24) & 0xFF;
Run Code Online (Sandbox Code Playgroud)

稍后只需将zpkg数组输出到文件。但是这不起作用;当我用 gzip 解压它时,错误信息是:

gzip: data stream error
gzip: test.gz: uncompress failed
Run Code Online (Sandbox Code Playgroud)

有人可以指出我做错了什么吗?



感谢 Mark Adler 和 Michael,我找到了一个可行的解决方案。

首先,正如马克指出的那样,我应该让 miniz 返回一个原始的 deflate 数据流。这可以通过传递-MZ_DEFAULT_WINDOW_BITS(注意减号)mz_deflateInit2()作为第四个参数来完成。查看 miniz 源代码,该compress2()函数最终调用mz_deflateInit2()with MZ_DEFAULT_WINDOW_BITS,这意味着添加 zlib 页眉和页脚。所以最简单的解决方法是在那里添加一个减号,这样我仍然可以使用该compress2()功能。(这对我有用,因为我只在一个地方调用这个函数)

其次,正如迈克尔所指出的,CRC 码应该在未压缩的数据上计算。所以我像这样修复它:

mz_ulong crc = mz_crc32(MZ_CRC32_INIT, pkg, pkgSize);
Run Code Online (Sandbox Code Playgroud)

做了以上两个更改后,gzip -d不再抱怨。

Mar*_*ler 2

compress2()生成一个 zlib 流,它是带有 zlib 标头和尾部的压缩数据。对于您正在做的事情,您只希望将原始 deflate 压缩流粘贴到手动生成的 gzip 标头和尾部中。

您可以:a) 丢弃输出的前两个和最后四个字节以compress2()剥离 zlib 标头和尾部,b) 使用deflateInit2()deflate()deflateEnd()代替compress2()并选择原始 deflate 格式,或 c) 使用相同的函数并代替选择 gzip 格式,并摆脱手动构建的 gzip 标头和尾部,因为deflate()它将为您完成此操作。

我推荐c)。