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 中文测试 哈哈哈[email protected]#$%^&*()_+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解压。

时间: 2024-10-27 03:08:12

zlib解压缩gzip的相关文章

linux笔记 文件的压缩与解压缩gzip、bzip2、xz、zip&unzip、tar打包、tar打包和压缩并用

压缩文件意义节省网络传输带宽,降低磁盘使用率.但会使用一定的cpu. 1.gzip 不支持压缩目录,gzip后直接跟文件名,在当前目录下压缩时,原文件会消失. #gzip filename 指定压缩目录:#gzip -c 123.txt > /tmp/123.txt.gz 将当前目录下123.txt文件压缩到tmp目录下名字为123.txt.gz 解压缩:#gzip -d file.gz #zcat file.gz  查看.gz文件内容 2.bzip2 不支持压缩目录,bzip2后可直接跟文件名

使用zlib实现gzip格式数据的压缩和解压

注意代码中的注释部分,这里设置是专门针对gzip的,缺少了就不行了,gzip压缩格式和其他格式的区别就在这里. Bytef 就是 unsigned char,uLong就是 unsigned long,这些别名的设置都在zconf.h文件里面. 这里压缩和解压缩的数据都可以用java的GZIPInputStream和GZIPOutputStream来对应解压缩和压缩. 代码片 #ifndef GZIP_H #define GZIP_H #include "zlib/zlib.h" /*

webservice(axis)接口上传文件附件 及 用zlib解压缩

webservice传文件,我平时用到的webservice框架也就是Axis和CXF,这两种框架都可以用DataHandler进行文件的传输,这种的传的是文件的内容,不会有文件名称,类型,所以这些得自己在接口中加字段:还有一种方式就是将文件转化成字节数组,再用Base64将字节数组编码成字符串类型放入接口字段中进行传输,接受的一方先解码然后存文件. 目前用到的就是后一种,无论前一种还是后一种,两种方式传输的文件都不能太大,前一种具体能传多大不太清楚,后一种十几兆或者二十多兆还是可以传的,只是传

在bootloader及IAP中使用zlib解压缩

原有的bootloader方案是在片内FLASH上面分成3块,bootloader区占一小块,然后剩下区域平分成两块,一块是运行区,一块是新固件临时存储区. 好在现在FLASH在系统成本中占的比例越来越低了,不然这样用肯定很奢侈浪费了. 在此方案基础上,我们还可以使用压缩功能,这样临时存储区可以更小一些,可以释放出更多空间给运行区. 压缩算法格式综合考虑后使用gzip,解压程序使用zlib. 因为gzip格式比较通用,方便压缩和调试.而解压所消耗的资源也尚可接受. 一般测试下来,gz所用的 de

node.js使用iconv-lite和zlib解决gzip压缩和gbk乱码

安装插件request,iconv-lite.zlib內置. 1.设置请求参数中的encoding为null,这样传入回调函数中的body将是一个buffer.(默认为utf8编码) 2.用zlib.gunzip()方法对body进行解压,解压的到的依然是个buffer. ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 request({     uri: url,     method: 'GET',     timeout: 5000,     encodi

golang zlib 压缩,解压缩

package main import ( "bytes" "compress/zlib" "fmt" "io" "os" ) //进行zlib压缩 func DoZlibCompress(src []byte) []byte { var in bytes.Buffer w := zlib.NewWriter(&in) w.Write(src) w.Close() return in.Bytes()

zlib学习小结

官方手册 : http://www.zlib.net/manual.html 参考连接 : http://blog.csdn.net/zhoudaxia/article/details/8039519 http://www.oschina.net/code/snippet_65636_22542 http://blog.163.com/bh_binghu/blog/static/94553512011626102054571/ 请多多支持以上作者... 另外,推荐下载源码同步学习. 研究了好久的

理解和使用zlib库 - 我个人的救赎

理解和使用zlib库 作者: 阙荣文 日期: 2016.6.2 0. 很多年以前我曾经写过一篇文章(http://blog.csdn.net/querw/article/details/1452041)简单介绍 zlib 的使用方法,老实说当时自己都不是很明白 zlib 是怎么回事,现在想起来那个时候年轻嘛,胆子大,脸皮厚...希望用一篇新的文章纪念少不更事的无知. 1. deflate算法, zlib 格式, gzip 格式 本文并不是一篇介绍压缩算法的文章,请读者自行查阅关于 LZ77 算法

Zlib库学习总结

zlib类库提供了很多种压缩和解压缩的方式,由于时间的关系我只学习一下内容,以下是我在实现web 服务器压缩数据网页中使用到一些函数和常用数据结构.常量等. zlib使用过程 压缩过程:deflateInit() ->deflate() ->deflateEnd();  对应的解压过程 inflateInit() ->  inflate() ->  inflateEnd(); 压缩过程:deflateInit2() ->deflate() ->deflateEnd();