简体   繁体   English

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

[英]How to use miniz to create a compressed file that can be decompressd by gzip?

I'm writing a program in C++, on windows platform. 我在Windows平台上用C ++编写程序。 I would like to compress some data storing in a char[] array, and output it to a file, and later I will upload the file to a unix server and I want it can be decompressed by gzip -d . 我想压缩存储在char[]数组中的一些数据,并将其输出到文件,稍后我将文件上传到unix服务器,我希望它可以通过gzip -d解压缩。

After a lot of research, I choose miniz . 经过大量的研究,我选择miniz Also, I found the gzip file format here . 另外,我在这里找到了gzip文件格式。

Here is the code snippet of creating gzip file: (sorry I didn't put the definition of some variables; they're defined somewhere else) 这是创建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;

And later just output the zpkg array to a file. 然后只需将zpkg数组输出到文件中。 However this doesn't work; 但这不起作用; when I decompress it with gzip, the error messsage is: 当我用gzip解压缩时,错误消息是:

gzip: data stream error
gzip: test.gz: uncompress failed

Can anybody please point me out what I'm doing wrong? 谁能指出我做错了什么?



Thanks for Mark Adler and Michael, I figure out a working solution. 感谢Mark Adler和Michael,我找到了一个有效的解决方案。

First, as Mark pointed out, I should make miniz return a raw deflate data stream. 首先,正如Mark指出的那样,我应该让miniz返回一个原始的deflate数据流。 This can be done by passing -MZ_DEFAULT_WINDOW_BITS (notice the minus sign) to mz_deflateInit2() as the fourth parameter. 这可以通过将-MZ_DEFAULT_WINDOW_BITS (注意减号)传递给mz_deflateInit2()作为第四个参数来完成。 Looking into the miniz source code, the compress2() function eventually calls the mz_deflateInit2() with MZ_DEFAULT_WINDOW_BITS , which means adding zlib header and footer. 展望miniz源代码, compress2()函数最终调用mz_deflateInit2()MZ_DEFAULT_WINDOW_BITS ,这意味着添加ZLIB页眉和页脚。 So the easiest fix is adding a minus sign there, so that I can still use the compress2() function. 所以最简单的解决方法是在那里添加一个减号,这样我仍然可以使用compress2()函数。 (this works for me because I only call this function at one place) (这对我有用,因为我只在一个地方调用此功能)

Second, as Michael pointed out, the CRC code should be calculated on uncompressed data. 其次,正如迈克尔指出的那样,CRC代码应该在未压缩数据上计算。 So I fix it like this: 所以我修复它:

mz_ulong crc = mz_crc32(MZ_CRC32_INIT, pkg, pkgSize);

After making the two changes above, gzip -d doesn't complain anymore. 完成上述两个更改后, gzip -d不再抱怨了。

compress2() produces a zlib stream, which is deflate compressed data with a zlib header and trailer. compress2()生成一个zlib流,它使用zlib头和尾部来压缩压缩数据。 For what you are doing, you want just the raw deflate compressed stream to stick in your manually generated gzip header and trailer. 对于您正在做的事情,您只需要将原始deflate压缩流粘贴到手动生成的gzip标头和预告片中。

You could either: a) discard the first two and last four bytes of the output of compress2() to strip the zlib header and trailer, b) use deflateInit2() , deflate() , and deflateEnd() instead of compress2() and select the raw deflate format, or c) use those same functions and instead select the gzip format, and get rid of your manually constructed gzip header and trailer since deflate() will do that for you. 您可以:a)丢弃compress2()输出的前两个和后四个字节以deflateInit2() zlib头和尾部,b)使用deflateInit2()deflate()deflateEnd()而不是compress2()和选择原始deflate格式,或c)使用相同的函数,而不是选择gzip格式,并摆脱手动构造的gzip头和预告片,因为deflate()将为你做这件事。

I recommend c). 我推荐c)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM