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 = ; if (data && ndata > ) {
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 + , , Z_DEFAULT_STRATEGY) != Z_OK) return -;
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 != && c_stream.total_out < *nzdata) {
if (deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -;
}
if (c_stream.avail_in != ) return c_stream.avail_in;
for (;;) {
if ((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;
if (err != Z_OK) return -;
}
if (deflateEnd(&c_stream) != Z_OK) return -;
*nzdata = c_stream.total_out;
return ;
}
return -;
} /* Uncompress gzip data */
/* zdata 数据 nzdata 原数据长度 data 解压后数据 ndata 解压后长度 */
int gzdecompress(Byte *zdata, uLong nzdata,
Byte *data, uLong *ndata)
{
int err = ;
z_stream d_stream = { }; /* decompression stream */
static char dummy_head[] = {
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + ) / * ) & 0xFF,
};
d_stream.zalloc = NULL;
d_stream.zfree = NULL;
d_stream.opaque = NULL;
d_stream.next_in = zdata;
d_stream.avail_in = ;
d_stream.next_out = data;
//只有设置为MAX_WBITS + 16才能在解压带header和trailer的文本
if (inflateInit2(&d_stream, MAX_WBITS + ) != Z_OK) return -;
//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 = ; /* 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 -;
}
}
else return -;
}
}
if (inflateEnd(&d_stream) != Z_OK) return -;
*ndata = d_stream.total_out;
return ;
}

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

zlib解压缩gzip的更多相关文章

  1. 在iPhone开发中实现解压缩gzip

    在iPhone开发中实现解压缩gzip是本文要介绍的内容,最近做的一个东西中,需要从网络获取xml文件,但是该文件用了gzip压缩的.搜索一 下有人说gzip压缩的用urlrequest可以自己解压, ...

  2. VB6之借助zlib实现gzip解压缩

    这是个简版的,可以拿来做下网页gzip的解压缩,整好我的webserver还不支持这个,有时间了就加上. zlib.dll下载请点击我! 模块zlib.bas的代码如下: 'code by lichm ...

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

    注意代码中的注释部分,这里设置是专门针对gzip的,缺少了就不行了,gzip压缩格式和其他格式的区别就在这里. Bytef 就是 unsigned char,uLong就是 unsigned long ...

  4. 在bootloader及IAP中使用zlib解压缩

    原有的bootloader方案是在片内FLASH上面分成3块,bootloader区占一小块,然后剩下区域平分成两块,一块是运行区,一块是新固件临时存储区. 好在现在FLASH在系统成本中占的比例越来 ...

  5. 压缩与解压缩 gzip bzip2 tar 命令

    gzip压缩与解压缩 命令  gzip -v   解压缩 gzip-d 操作如下. 压缩 .可以看到源文件有5171大小,压缩后,变成了1998大小. 解压缩 .解压缩之后可以看到,原来的man_db ...

  6. golang zlib 压缩,解压缩

    package main import ( "bytes" "compress/zlib" "fmt" "io" &qu ...

  7. Node基础:资源压缩之zlib

    概览 做过web性能优化的同学,对性能优化大杀器gzip应该不陌生.浏览器向服务器发起资源请求,比如下载一个js文件,服务器先对资源进行压缩,再返回给浏览器,以此节省流量,加快访问速度. 浏览器通过H ...

  8. ZLIB 库

    zlib 编辑 zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表.zlib使用DEFLATE算法,最初是为libp ...

  9. NodeJS学习笔记 (1)资源压缩-zlib(ok)

    原文: https://github.com/chyingp/nodejs-learning-guide/blob/master/README.md 自己的跟进学习: 概览 做过web性能优化的同学, ...

随机推荐

  1. 基于spec评论作品 - 探路者 贪吃蛇

    基于spec评论作品,试用(并截图)所有其他小组的Alpha作品,与软件功能说明书对比,评论Alpha作品对软件功能说明书的实现. 首先通过命令行进入到游戏主页面中. 因为软件没有编译为exe程序,所 ...

  2. 团队作业——王者光耀:team

    光耀101  <光耀101>是福州大学数计学院计算机专业推出的中国首部程序猿脱发养成节目.由张栋担任发起人,刘晨瑶.畅畅担任导师.  该节目召集了你猜多少位选手,通过任务.训练.考核,让选 ...

  3. 线段树---成段更新hdu1698 Just a Hook

    hdu1698 Just a Hook 题意:O(-1) 思路:O(-1) 线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息) 题意:给一组棍子染色,不同 ...

  4. [pascal入门]数组

    一.本节目标 本节我们将要讲述数组.本节目标: 一维数组 二维数组 字符数组 二.一维数组 我们通过一个案例来简单的理解数组.班主任要计算班级里面50个同学数学成绩的平均成绩,道理上讲这是一个比较简单 ...

  5. StringBuilder、StringBuffer和String三者的联系和区别

    String 类    String的值是不可变的,这就导致每次对String的操作都会生成新的String对象,不仅效率低下,而且大量浪费有限的内存空间.    String a = "a ...

  6. 复利计算程序单元测试(C语言)

    对我们和复利计算程序,写单元测试. 有哪些场景? 期待的返回值 写测试程序. 运行测试. 我的复利计算程序是用C语言写的,不懂使用C语言的测试工具,所以用C语言的运行结果来反映测试结果. 测试模块(场 ...

  7. 使用Kettle导出excel

    1.开发背景 在web项目中,经常会需要查询数据导出excel,以前比较常见的就是用poi.使用poi的时候也有两种方式,一种就是直接将集合一次性导出为excel,还有一种是分批次追加的方式适合数据量 ...

  8. vue shorthands

    vue shorthands : & @ https://vuejs.org/v2/guide/syntax.html#Shorthands v-for https://vuejs.org/v ...

  9. BZOJ4888 Tjoi2017异或和(树状数组)

    化为前缀和相减.考虑每一位的贡献.则需要快速查询之前有几个数和当前数的差在第k位上为1.显然其与更高位是无关的.于是用BIT维护后k位的数的出现次数,瞎算一算即可. // luogu-judger-e ...

  10. 洛谷 P1344 [USACO4.4]追查坏牛奶Pollutant Control

    题目描述 你第一天接手三鹿牛奶公司就发生了一件倒霉的事情:公司不小心发送了一批有三聚氰胺的牛奶.很不幸,你发现这件事的时候,有三聚氰胺的牛奶已经进入了送货网.这个送货网很大,而且关系复杂.你知道这批牛 ...