zlib解压缩gzip

zlib是个著名的开源解压缩库,gzip是一种压缩文件格式。

zlib可以压缩原始数据并输出gzip文件,gzip文件中除了压缩数据外,还有描述这些数据的文件头,所以当原始数据较小时,会出现zlib的压缩输出会比原始数据还大的情况。

zlib能使用一个gzip数据头,zlib数据头或者不使用数据头压缩数据。
通常情况下,数据压缩使用zlib数据头,因为这提供错误数据检测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者不知道压缩数据在什么地方结束。
gzip数据头比zlib数据头要大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件,但是它相当轻松的通过把压缩数据写入到一个有gzip文件头的文件中。
zlib提供的工具接口:compress()和decompress()是压缩内存数据流,并不带gzip文件头和尾。java的解压缩用的是类似的一套东西:java.util.zip.GZIPInputStream,请注意java的这一套是用来解压完整的gzip文件格式的,因此如果c语言用zlib的compress()压缩数据后传给java,java端是解压缩不了的,会提示格式错误。
zlib创建gzip文件很简单,跟C语言读写文件很相似:
/* 原始数据 */
    unsigned char strSrc[] = "hello world! aaaaa 中文测试 哈哈哈~!@#$%^&*()_+yes";
    unsigned long srcLen = sizeof(strSrc);
    printf("Src string:%s\nLength:%ld\n", strSrc, srcLen);
    /* 压缩 */
    ::gzFile file = ::gzopen("d:/1.gz", "wb");
    if (file != NULL)
    {
        printf("GZip file Writing ...\n");
        ::gzwrite(file, strSrc, srcLen);
        printf("done.\n");
    }
    ::gzclose(file);

如果想在内存中输出gzip格式的数据流,而不是写文件,则用以下方法:

/* Compress gzip data */
/* data 原数据 ndata 原数据长度 zdata 压缩后数据 nzdata 压缩后长度 */
int gzcompress(Bytef *data, uLong ndata,
               Bytef *zdata, uLong *nzdata)
{
    z_stream c_stream;
    int err = 0;

    if (data && ndata > 0) {
        c_stream.zalloc = NULL;
        c_stream.zfree = NULL;
        c_stream.opaque = NULL;
        //只有设置为MAX_WBITS + 16才能在在压缩文本中带header和trailer
        if (deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
                         MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY) != Z_OK) return -1;
        c_stream.next_in = data;
        c_stream.avail_in = ndata;
        c_stream.next_out = zdata;
        c_stream.avail_out = *nzdata;
        while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) {
            if (deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;
        }
        if (c_stream.avail_in != 0) return c_stream.avail_in;
        for (;;) {
            if ((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;
            if (err != Z_OK) return -1;
        }
        if (deflateEnd(&c_stream) != Z_OK) return -1;
        *nzdata = c_stream.total_out;
        return 0;
    }
    return -1;
}

/* Uncompress gzip data */
/* zdata 数据 nzdata 原数据长度 data 解压后数据 ndata 解压后长度 */
int gzdecompress(Byte *zdata, uLong nzdata,
                 Byte *data, uLong *ndata)
{
    int err = 0;
    z_stream d_stream = { 0 }; /* decompression stream */
    static char dummy_head[2] = {
        0x8 + 0x7 * 0x10,
        (((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
    };
    d_stream.zalloc = NULL;
    d_stream.zfree = NULL;
    d_stream.opaque = NULL;
    d_stream.next_in = zdata;
    d_stream.avail_in = 0;
    d_stream.next_out = data;
    //只有设置为MAX_WBITS + 16才能在解压带header和trailer的文本
    if (inflateInit2(&d_stream, MAX_WBITS + 16) != Z_OK) return -1;
    //if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
    while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
        d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
        if ((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
        if (err != Z_OK) {
            if (err == Z_DATA_ERROR) {
                d_stream.next_in = (Bytef*)dummy_head;
                d_stream.avail_in = sizeof(dummy_head);
                if ((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) {
                    return -1;
                }
            }
            else return -1;
        }
    }
    if (inflateEnd(&d_stream) != Z_OK) return -1;
    *ndata = d_stream.total_out;
    return 0;
}

以上这两种方法的输出都可以被java.util.zip.GZIPInputStream解压。

(0)

相关推荐

  • ubuntu下安装nginx时PCRE库、zlib库、OpenSSL库的安装

    Nginx是高度自由化的Web服务器,它的功能是由许多模块来支持.如果使用了某个模块,这个模块使用了一些类似zlib或OpenSSL等的第三方库,那么就必须先安装这些软件.Ubuntu下不像在cent ...

  • Nginx 开启gzip压缩,减轻服务器压力

    Nginx 开启gzip压缩,减轻服务器压力 优化服务器的方案有很多种.常用的是缓存静态文件和开启gzip,还有cdn加速.使用cache缓存数据,本次主要根据自身的网站.采取的优化方案. 首先.Vi ...

  • PHP的zlib压缩工具扩展包学习

    PHP的zlib压缩工具扩展包学习 总算到了我们压缩相关扩展的最后一篇文章了,最后我们要学习的也是 Linux 下非常常用的一种压缩格式:.gz 的压缩扩展.作为 PHP 的自带扩展,就像 zip 一 ...

  • 怎么给电脑下载解压缩软件

    首发怎么给电脑下载解压缩软件 清风霁月1W次浏览2018.10.15 怎么给电脑下载解压缩软件呢?下面小编来教大家. 开启分步阅读模式 操作方法 01 首先,我们打开我们的电脑,然后我们双击电脑桌面上 ...

  • 7-zip才是解压缩软件中的业界良心!

    前言 如果问你的电脑必装的软件有哪些? 压缩软件必须是必装的软件之一! 很多朋友都会用到国产的一些压缩软件,但这其实可能并非是明智之选. 今天给大家推荐一款开源的解压缩软件,堪称鼻祖! 7-Zip这款 ...

  • [PHP小课堂]PHP的zlib压缩工具扩展包学习

    [PHP小课堂]PHP的zlib压缩工具扩展包学习 关注公众号:[硬核项目经理]获取最新文章 添加微信/QQ好友:[xiaoyuezigonggong/149844827]免费得PHP.项目管理学习资 ...

  • BetterZip用于解压缩的预设设置

    BetterZip解压缩软件的偏好设置中的"预置"选项卡中包含了"解压缩"和"保存"两个选项,其中相同的部分是左侧的预设列表和右侧的预设名称 ...

  • (7条消息) gzip头部格式

    注意两个加好表示一个字节(8位) gzip头的格式: +---+---+---+---+---+---+---+---+---+---+ |ID1|ID2|CM |FLG| MTIME |XFL|OS ...

  • gzip命令

    sunxx1986 2011-09-27 10:56:29 命令: gzip 语法:gzip [选项] 压缩(解压缩)的文件名 -c 将输出写到标准输出上,并保留原有文件. -d 将压缩文件解压. - ...