ZLIB 库

zlib

编辑

zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。此函式库为自由软件,使用zlib授权。截至2007年3月,zlib是包含在Coverity的美国国土安全部赞助者选择继续审查的开源项目。

中文名
zlib
外文名
zlib
定    义
提供数据压缩用的函数库
开    发
Jean-loup Gailly与Mark Adler

目录

  1. 特性
  2. 数据头(header)
  3. 算法
  4. 使用资源
  1. 策略
  2. 错误处理
  3. 数据长度
  4. 业界应用
  1. 使用范例
  2. zlib许可

特性

编辑

数据头(header)

zlib能使用一个gzip数据头,zlib数据头或者不使用数据头压缩数据。

通常情况下,数据压缩使用zlib数据头,因为这提供错误数据检测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者不知道压缩数据在什么地方结束。

gzip数据头比zlib数据头要大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件,但是它相当轻松的通过把压缩数据写入到一个有gzip文件头的文件中。

算法

目前zlib仅支持一个LZ77的变种算法,DEFLATE的算法。

这个算法使用很少的系统资源,对各种数据提供很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。(尽管zip文件格式也支持几种其他的算法)。

看起来zlib格式将不会被扩展使用任何其他算法,尽管数据头可以有这种可能性。

使用资源

函数库提供了对处理器和内存使用控制的能力

不同的压缩级别数值可以指示不同的压缩执行速度。

还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的。

策略

压缩可以针对特定类型的数据进行优化

如果你总是使用zlib库压缩压缩特定类型的数据,那么可以使用有针对性的策略可以提高压缩效率和性能。例如,如果你的数据包含很长的重复数据,那么可以用RLE(运行长度编码)策略,可能会有更好的结果。

对于一般的数据,默认的策略是首选。

错误处理

错误可以被发现和跳过

数据混乱可以被检测(只要数据和zlib或者gzip数据头一起被写入-参见上面)

此外,如果全刷新点(full-flush points)被写入到压缩后的数据流中,那么错误数据是可以被跳过的,并且解压缩将重新同步到下个全刷新点。(错误数据的无错恢复被提供)。全刷新点技术对于在不可靠的通道上的大数据流是很有用的,一些过去的数据丢失是不重要的(例如多媒体数据),但是建立太多的全刷新点会极大的影响速度和压缩。

数据长度

对于压缩和解压缩,没有数据长度的限制

重复调用库函数允许处理无限的数据块。一些辅助代码(计数变量)可能会溢出,但是不影响实际的压缩和解压缩。

当压缩一个长(无限)数据流时,最好写入全刷新点。

业界应用

编辑

今天,zlib是一种事实上的业界标准,以至于在标准文档中,zlib和DEFLATE常常互换使用。数以千计的应用程序直接或间接依靠zlib压缩函式库,包括:

* Linux核心:使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。

* libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。

* Apache:使用zlib实作http 1.1。

* OpenSSH、OpenSSL:以zlib达到最佳化加密网络传输。

* FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。

* rsync:以zlib最佳化远端同步时的传输。

* The dpkg and RPM package managers, which use zlib to unpack files from compressed software packages.

* Subversion 、Git和 CVS 版本控制 系统,使用zlib来压缩和远端仓库的通讯流量。

* dpkg和RPM等包管理软件:以zlib解压缩RPM或者其他封包

因为其代码的可移植性,宽松的许可以及较小的内存占用,zlib在许多嵌入式设备中也有应用。

使用范例

编辑

以下代码可直接用于解压HTTP gzip

#include <stdlib.h>

#include <string.h>

#include <errno.h>

#include <zlib.h>

/* Compress data */

int zcompress(Bytef *data, uLong ndata,

Bytef *zdata, uLong *nzdata)

{

z_stream c_stream;

int err = 0;

if(data && ndata > 0)

{

c_stream.zalloc = (alloc_func)0;

c_stream.zfree = (free_func)0;

c_stream.opaque = (voidpf)0;

if(deflateInit(&c_stream, Z_DEFAULT_COMPRESSION) != 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;

}

/* Compress gzip data */

int gzcompress(Bytef *data, uLong ndata,

Bytef *zdata, uLong *nzdata)

{

z_stream c_stream;

int err = 0;

if(data && ndata > 0)

{

c_stream.zalloc = (alloc_func)0;

c_stream.zfree = (free_func)0;

c_stream.opaque = (voidpf)0;

if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED,

-MAX_WBITS, 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 data */

int zdecompress(Byte *zdata, uLong nzdata,

Byte *data, uLong *ndata)

{

int err = 0;

z_stream d_stream; /* decompression stream */

d_stream.zalloc = (alloc_func)0;

d_stream.zfree = (free_func)0;

d_stream.opaque = (voidpf)0;

d_stream.next_in = zdata;

d_stream.avail_in = 0;

d_stream.next_out = data;

if(inflateInit(&d_stream) != 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) return -1;

}

if(inflateEnd(&d_stream) != Z_OK) return -1;

*ndata = d_stream.total_out;

return 0;

}

/* HTTP gzip decompress */

int httpgzdecompress(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 = (alloc_func)0;

d_stream.zfree = (free_func)0;

d_stream.opaque = (voidpf)0;

d_stream.next_in = zdata;

d_stream.avail_in = 0;

d_stream.next_out = data;

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;

}

/* Uncompress gzip data */

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 = (alloc_func)0;

d_stream.zfree = (free_func)0;

d_stream.opaque = (voidpf)0;

d_stream.next_in = zdata;

d_stream.avail_in = 0;

d_stream.next_out = data;

if(inflateInit2(&d_stream, -MAX_WBITS) != 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;

}

#ifdef _DEBUG_ZSTREAM

#define BUF_SIZE 65535

int main()

{

char *data = "kjdalkfjdflkjdlkfjdklfjdlkfjlkdjflkdjflddajfkdjfkdfaskf;ldsfk;ldakf;ldskfl;dskf;ld";

uLong ndata = strlen(data);

Bytef zdata[BUF_SIZE];

uLong nzdata = BUF_SIZE;

Bytef odata[BUF_SIZE];

uLong nodata = BUF_SIZE;

memset(zdata, 0, BUF_SIZE);

//if(zcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)

if(gzcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)

{

fprintf(stdout, "nzdata:%d %s\n", nzdata, zdata);

memset(odata, 0, BUF_SIZE);

//if(zdecompress(zdata, ndata, odata, &nodata) == 0)

if(gzdecompress(zdata, ndata, odata, &nodata) == 0)

{

fprintf(stdout, "%d %s\n", nodata, odata);

}

}

}

#endif

zlib许可

编辑

zlib许可[1]  是一个自由软件授权协议,但并非copyleft。Box2D就使用了zlib许可。

参考资料
时间: 2024-10-12 01:24:56

ZLIB 库的相关文章

[C/C++]_[初级]_[使用zlib库压缩文件]

场景: 1. WIndows上没找到系统提供的win32 api来生成zip压缩文件, 有知道的大牛麻烦留个言. 2. zlib比较常用,编译也方便,使用它来做压缩吧.MacOSX平台默认支持zlib库. http://zlib.net 3. zlib库里的 src\contrib\minizip\minizip.c  里有压缩例子, 我现在使用的是zlib 1.2.5,用vs2010编译完.下载地址: http://download.csdn.net/detail/infoworld/8177

Zlib库的安装与使用

在实际应用中经常会遇到要压缩数据的问题,常见的压缩格式有zip和rar,而Linux下那就更多了,bz2,gz,xz什么的都有,单单Linux下的解压和压缩命令就有好多呢?没有什么好不好的.查了资料,应该是zlib这个比较简单好用.应用也广,所以就准备用这个了. 下载Zlib库,地址: http://zlib.net/zlib128.zip 用wget下载,然后再用unzip解压一下,然后就像一般软件一样 ./configure && make && make instal

Windows下zlib库和libPng库的编译和使用

关于zlib库和libpng是干嘛的,我就不说了,度娘和谷歌都能告诉你.这里主要记录下windows下如何利用vs2010编译和使用这两个库. 一.zlib库的编译 首先要下载这个库,这个谷歌和百度也都可以找得到的.我下载的是zlib-1.2.5,下载完解压出来即可.下边就开始编译吧.(包括动态库和静态库两种) 1. 首先开启VS2010的Command Prompt (32bit),也就是命令提示窗口. 2. 进入到zlib-1.2.5/contrib/masmx86目录,执行bld_ml32

Python:编译Python时,如何代上zlib库?

在Fedora下需要测试一些东西,所以不打算用系统自带的Python,需要自己编译一个.编译好后,需要安装pip,pip需要setuptools, 而setuptools需要zlib库,在执行 ./configure --help ./configure --prefix=~/.local/python2.7 --with-zlib 没有看到有--with-zlib这个选项,非常奇怪,但是还是用了这个选项,事实是,即使选择这个选项,新的版本Python依旧没有zlib库. 1. 其实,答案非常简

【转】 C++使用zlib库(-)

来自:  http://blog.chinaunix.net/uid-24607609-id-2118143.html 今天看到一个gzopen函数,搜了一下他的系列函数,及相关用法 C++使用zlib库(-) 2010-10-07 09:37:35 分类: C/C++ 1.gzopen打开经过zlib算法压缩的文件gzFile gz = gzopen(char* filename,"rb");打开一个zlib的流,使用该流可以对文件进行读的操作2.gzeof用法与C中的feof相似,

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

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

[Zlib]_[初级]_[使用zlib库解压提取文件]

场景: 1. zlib库跨平台,Windows和MacOSX都可以使用,还支持64位编译,轻量级,没有不用的道理. 2. 处理.zip,apk,docx文件时,因为这类文件都是zip格式,使用zlib能方便提取压缩文件里的数据. 方法: 1. 除了要使用zlib库本身,还需要使用zlib里的contrib目录minizip部分头文件和.c文件. zlib-1.2.5/src/contrib/minizip/unzip.h unzip.c,ioapi.c,ioapi.h (windows还需要 i

linux编译zlib库的动态库so

转载请注明出处:帘卷西风的专栏(http://blog.csdn.net/ljxfblog) zlib库是一个强大的通用的开源压缩库,用途比较广,在windows下能够很容易的编译或者拿到编译成功的二进制文件.但是linux下的比较少,本文记录一下如何编译. zlib官方网站:http://www.zlib.net 首先,下载源码来安装zlib软件包.目前最新的版本是1.2.8. #wget http://www.zlib.net/zlib-1.2.8.tar.gz 然后,解压下载的文件包. #

QT+OpenGL(02)-- zlib库的编译

1.zlib库的下载 http://www.zlib.net/ zlib1211.zip 2.解压 3.进入  zlib1211\zlib-1.2.11\contrib\vstudio\vc14 目录 4.用VS打开zlibvc.sln文件 5.点击菜单"生成"->"生成解决方案" 已生成的zlibwapi.lib和zlibwapi.dll在目录zlib1211\zlib-1.2.11\contrib\vstudio\vc14\x64\ZlibDllRelea