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

moiiocjp  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(188)

我在写一个程序,在C++,在Windows平台上,我想压缩存储在char[]数组中的一些数据,并将其输出到一个文件,稍后我将上传文件到一个unix服务器,我想它可以解压缩的gzip -d
经过大量的研究,我选择miniz。此外,我发现gzip文件格式here
下面是创建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;

字符串
然后将zpkg数组输出到一个文件中。但是这不起作用;当我用gzip压缩它时,错误消息是:

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


有人能指出我哪里做错了吗?
感谢马克·阿德勒和迈克尔,我想出了一个可行的解决方案。
首先,正如Mark指出的,我应该让miniz返回一个原始的deflate数据流。查看miniz源代码,compress2()函数最终使用MZ_DEFAULT_WINDOW_BITS调用mz_deflateInit2(),这意味着添加zlib的页眉和页脚。所以最简单的解决方法是在那里添加一个减号,这样我仍然可以使用compress2()函数。(这对我来说很有效,因为我只在一个地方调用这个函数)
第二,正如Michael指出的,CRC码应该在未压缩的数据上计算。所以我这样修复它:

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


在做了上面的两个修改之后,gzip -d不再抱怨了。

ljo96ir5

ljo96ir51#

compress2()产生一个zlib流,它是一个带有zlib头和尾的deflate压缩数据。对于你正在做的事情,你只需要原始的deflate压缩流粘在你手动生成的gzip头和尾中。
您可以:a)丢弃compress2()的输出的前两个和最后四个字节以剥离zlib头部和尾部,b)使用deflateInit2()deflate()deflateEnd()而不是compress2()并选择原始deflate格式,或者c)使用那些相同的函数并选择gzip格式,并摆脱你的手动构造的gzip头和尾部,因为deflate()将为你做。
我推荐C)。

laximzn5

laximzn52#

使用上面的问题和答案,我能够编写工作代码。

#include "miniz_cpp.hpp" //https://github.com/nyq/miniz-cpp/tree/master
                         //based on miniz 3.0.2
using namespace miniz_cpp;
void Save_gz_file(std::string sFileName, std::string &data)
{
    std::string sDeflated = "";
    unsigned long iDeflated = data.length()*2+18;
    sDeflated.reserve(iDeflated);
    sDeflated.append("\x1f\x8b\x08\0\0\0\0\0\0\xff", 10);

    mz_stream stream;
    memset(&stream, 0, sizeof(stream));

    stream.next_in = (unsigned char *) data.data();
    stream.avail_in = (mz_uint32) data.length();
    stream.next_out = (unsigned char *) (sDeflated.data() + 10);
    stream.avail_out = (mz_uint32) iDeflated;

    int result = mz_deflateInit2(&stream, MZ_BEST_COMPRESSION,
                 MZ_DEFLATED, -MZ_DEFAULT_WINDOW_BITS, 9,
                 MZ_DEFAULT_STRATEGY);

    if(result == MZ_OK)
    {
        result = mz_deflate(&stream, MZ_FINISH);
        if(result == MZ_STREAM_END) 
        {
            std::ofstream some_file(sFileName);
            some_file.write(sDeflated.data(), stream.total_out + 10); 
            uLong crc = mz_crc32(MZ_CRC32_INIT, (mz_uint8*) (data.data()),
                                 data.length());
            some_file.write((const char*) &crc, 4);
            uLong len = data.length();
            some_file.write((const char*) &len, 4);                            
        }
        mz_deflateEnd(&stream);   
    }
}

字符串

相关问题