- 浏览: 151351 次
- 性别:
- 来自: 北京
文章分类
最新评论
zlib库剖析(1):实现概览
本文整理自zlib.net以及zlib 1.2.7的手册页http://zlib.net/manual.html。
zlib是一套免费、通用、法律上不受限制的无损数据压缩库,可以在任何硬件及操作系统上使用。zlib数据格式可以跨平台移植。不像Unix compress(1)和GIF图像格式中使用的LZW压缩方法,当前zlib中使用的压缩算法不会扩充数据(LZW在极端情况下能使文件大小变为原来2 倍或3倍)。zlib的内存印迹也独立于输入数据,并且在压缩时能够被减小。zlib由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用抽象化的DEFLATE算法,最初是为libpng函数库所写的,后来普遍为许多软件所使用。此函数库为自由软件,使用zlib授权。
zlib授权是一个自由软件授权协议,但并非copyleft。协议原文在http://www.gzip.org/zlib /zlib_license.html。最新版本为1.2.2,2004年10月3日发布。版权持有人为Jean-loup Gailly和Mark Adler(1995-2004),类似于BSD许可。任何人都可以使用本软件,用于任何目的,包括闭源的商业应用。源码的修改和重新分发都是自由的,除了必须注明来源,并在发布的软件中保留此授权协议副本。
1、当前版本
#define ZLIB_VERSION "1.2.7"
#define ZLIB_VERNUM 0x1270
2、功能特性
zlib压缩库提供内存内压缩/解压缩函数。包括对解压数据完整性检查。这个版本只支持一种压缩方式(deflation),但是以后其他的算法也会被加入进来,并且保持同样的流接口。如果缓存区足够大,压缩被一次完成(例如输入文件被mmap了),否则就重复调用压缩。在后一种情况,程序必须在每次调用时提供更多的输入或更多输出空间。
本压缩库使用的默认压缩数据格式为zlib格式(在RFC 1950中描述),它是对deflate流(在RFC 1951中描述)的一种封装。本压缩库也支持对gzip(.gz)格式文件的读写操作,操作接口以"gz"开头,和stdio相似。gzip格式与 zlib格式不同,在RFC 1952中描述,是对deflate流的另一种封装。
本压缩库不安装任何信号处理器,解码器检查压缩数据的一致性,所以,即使在有损坏的输入情况下,本压缩库也不会崩溃。
(1)数据头
zlib能使用gzip数据头(header)、zlib数据头或者不使用数据头压缩数据。通常情况下,数据压缩使用zlib数据头,因为这提供错误数据检测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者知道压缩数据在什么地方结束。
gzip数据头比zlib数据头要大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件,但是它能够相当轻松的通过把压缩数据写入到一个有gzip文件头的文件中。
(2)算法
目前zlib仅支持一个LZ77的变种算法,即DEFLATE的算法。这个算法使用很少的系统资源,对各种数据提供很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。(尽管zip文件格式也支持几种其他的算法)。看起来zlib格式将不会被扩展使用任何其他算法,尽管数据头可以有这种可能性。
(3)使用资源
函式库提供了对处理器和内存使用控制的能力。不同的压缩级别数值可以指示不同的压缩执行速度。还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的。
(4)策略
压缩可以针对特定类型的数据进行优化。若使用者总是使用zlib压缩特定类型的数据,那么可以使用有针对性的策略可以提高压缩效率和性能。例如,如果使用者的数据包含很长的重复数据,那么可以用RLE(运行长度编码)策略,可能会有更好的结果。对于一般的数据,默认的策略是首选。
(5)错误处理
错误可以被发现和跳过,数据混乱可以被检测(只要数据和zlib或者gzip数据头一起被写入)。此外,如果全刷新点(full-flush points)被写入到压缩后的数据流中,那么错误数据是可以被跳过的,并且解压缩将重新同步到下个全刷新点(错误数据的无错恢复被提供)。全刷新点技术对于在不可靠的通道上的大数据流是很有用的,一些过去的数据丢失是不重要的(例如多媒体数据),但是建立太多的全刷新点会极大的影响速度和压缩。
(6)数据长度
对于压缩和解压缩,没有数据长度的限制。重复调用库函数允许处理无限的数据块。一些辅助代码(计数变量)可能会溢出,但是不影响实际的压缩和解压缩。当压缩一个长(无限)数据流时,最好写入全刷新点。
(7)使用zlib的软件
今天,zlib是一种事实上的业界标准,以至于在标准文档中,zlib和DEFLATE常常互换使用。数以千计的应用程序直接或间接依靠zlib压缩函式库(参考http://zlib.net/apps.html),包括:
Linux核心:使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。
libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。
Apache:使用zlib实作http 1.1。
OpenSSH、OpenSSL:以zlib达到最佳化加密网络传输。
FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。
rsync:以zlib最佳化远端同步时的传输。
Subversion 、Git和 CVS等版本控制系统:使用zlib来压缩和远端仓库的通讯流量。
dpkg和RPM等包管理软件:以zlib解压缩RPM或者其他封包。
另外,zlib被用在很多其他的编程语言中。在Java中可通过java.utl.zip使用zlib库;Python中通过import zlib使用zlib库;Perl的zlib接口可在CPAN找到;Tcl的zlib接口参看http://wiki.tcl.tk/4610。因为其代码的可移植性,宽松的授权许可以及较小的内存占用,zlib在许多嵌入式设备中也有应用。
在16-bit系统上,函数zalloc和zfree必须能够分配精确的65536字节,但如果定义了符号MAXSEG_64K(参看 zconf.h),则并不需要分配比这更多的空间。在MSDOS上,zalloc返回的65536字节对象的指针必须把偏移规格化为0,默认的分配函数会保证这一点(参看zutil.c)。为了减少内存需求,并且避免64K对象的分配,可以带-DMAX_WBITS=14编译参数(参看zconf.h)来编译zlib库,这样会牺牲一点压缩率。
字段total_in和total_out可用于统计和进程报告。在压缩后,total_in表示解压数据总大小,它可以被解压工具使用,特别是如果解压工具想一步之内解压所有的数据。
4、常量
(1)ZEXTERN const char * ZEXPORT zlibVersion OF((void));
应用程序会比较zlibVersion和ZLIB_VERSION的一致性。如果第一个字不同,说明zlib和应用程序使用的zlib.h是不一致的。这个检查将被defalteInit和infalteInit自动调用。
(2)ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
为压缩初始化内部流的状态。字段zalloc, zfree和opaque必须在调用之前初始化。如果zalloc和zfree被设为Z_NULL,deflateInit用默认分配函数来更新它们。压缩级别必须是define Z_DEFAULT_COMPRESSION,或者0到9之间,1为最快速度,9为最好的压缩率,0表示不作任何压缩(输入数据简单地被拷贝成一块)。 Z_DEFAULT_COMPRESSION为默认压缩级别,它在速度和压缩率之间取一个折衷(当前等于级别6)。函数成功时返回Z_OK,否则返回相应的错误码(Z_MEM_ERROR, Z_STREAM_ERROR或Z_VERSION_ERROR)。deflateInit不执行任何压缩动作,压缩动作由deflate()来执行。
(3)ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
压缩尽可能多的数据,直到输入缓冲区变空或输出缓冲区变满。它可能引入一些输出延迟(读取输入但不产生任何输出),除非强制刷新缓冲区。本函数执行以下一个或两个动作:
* 压缩从next_in开始的输入数据,并且更新相应的next_in和avail_in。如果不能处理所有的输入(因为输出缓冲区已满),next_in和avail_in会作相应更新,并且下一次调用deflate()时在这个点处恢复执行。
* 生成从next_out开始的输出,并且更新相应的next_out和avail_out。如果参数flush为非零,则本行为强制执行。强制频繁地刷新会降低压缩率,因此这个参数应该只在必要时才设置(在交互式应用程序中)。有些输出即使flush没有被设置也会生成。
(4)ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
所有为当前流分配的动态数据结构被释放。本函数抛弃任何未处理的输入,并且不会刷新任何挂起的输出。成功时返回Z_OK,流状态不一致时返回 Z_STREAM_ERROR,流过早被释放时(一些输入或输出被抛弃了)返回Z_DATA_ERROR。在错误情形中,msg信息可能被设置,然后指向一个静态字符串。
(5)ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
为解压初始化内部流状态。字段next_in, avail_in, zalloc, zfree和opaque必须在调用之前初始化。如果next_in不等于Z_NULL且avail_in足够大(准确的值取决于压缩方式),inflateInit从zlib头部确定压缩方式,然后分配所有数据结构。否则分配将会被推迟到第一次调用inflate。如果zalloc和 zfree被设为Z_NULL,inflateInit用默认分配函数来更新它们。函数返回 Z_OK,Z_MEM_ERROR,Z_VERSION_ERROR或Z_STREAM_ERROR。
(6)ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
解压尽可能多的数据。直到输入缓冲区变空或输出缓冲区变满。它可能引入一些输出延迟(读取输入但不产生任何输出),除非强制刷新缓冲区。本函数执行以下一个或两个动作:
* 解压从next_in开始的输入数据,并且更新相应的next_in和avail_in。如果不能处理所有的输入(因为输出缓冲区已满),next_in会作相应更新,并且下一次调用inflate()时在这个点处恢复执行。
* 生成从next_out开始的输出,并且更新相应的next_out和avail_out。inflate()生成尽可能多的输出,直到没有更多的输入或者输出缓冲区已满。flush参数可以是Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,Z_BLOCK或Z_TREES。
(7)ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
所有为这个stream动态分派的数据结构在这被释放。 这个函数丢弃所有未处理的输入,并且不会刷新任何挂起的输出。如果成功,inflateEnd返回Z_OK;如果stream是不一致的,返回 Z_STREAM_ERROR,在错误情形中,msg信息可能被设置,然后指向一个静态字符串。
6、高级函数
以下函数用于一些特殊的应用中:
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy));
ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength));
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source));
ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy));
ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain));
ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen));
ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, unsigned *pending, int *bits));
ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value));
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head));
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits));
ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength));
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source));
ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits));
ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value));
ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head));
ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window));
ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc));
ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
7、实用函数
以下实用函数的实现建立在前面介绍的基本面向流的函数上。为了简化接口,设置了一些默认选项(压缩级别,内存使用,标准内存分配器功能)这些实用函数的源代码很容易被修改,如果你要实现一些特殊选项。
(1)ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
压缩source buffer到destination buffer。sourceLen是source buffer的长度(byte)。调用前,destLen是destination buffer的总共长度(byte),它必须至少是compressBound(sourceLen)的返回值,一般为sourceLen长度的0.1% 再加上12个byte。退出前,destLen是实际的compressed buffer长度。如果输入文件是mmap的,这个函数可以一次压缩整个文件。如果压缩成功返回Z_OK, 如果没有足够的内存返回Z_MEM_ERROR,如果输出缓冲区中没有足够的空间返回Z_BUF_ERROR。
(2)ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level));
与compress功能一样,只不过多了一个level参数。参数level为压缩级别,与defalteInit中的含义一样。如果level是无效的,返回Z_STREAM_ERROR。
(3)ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
返回compressed size的上限,在sourceLen个字节上执行copress()或compress2()后。在调用compress()或compress2() 分配destination buffer之前,本函数可用于计算的destLen。
(4)ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
解压source buffer到destination buffer。sourceLen是source buffer的长度(byte)。调用前,destLen是destination buffer的总共长度(byte),它必须足够大以容纳全部解压后的数据(解压后的数据大小必须在先前由压缩工具保存好,然后通过一些机制传给解压工具,这种机制不在本压缩库的讨论范围内)。退出前,destLen是实际的compressed buffer长度。如果输入文件是mmap的,这个函数可以一次解压整个文件。如果解压成功返回Z_OK,如果没有足够的内存返回 Z_MEM_ERROR,如果输出缓冲区中没有足够的空间返回Z_BUF_ERROR,如果输入数据有损坏返回Z_DATA_ERROR。在没有足够空间的情况下,uncompress()用解压数据填充输出缓冲区,直到空间末尾为上。
(5)下面是gzip文件访问函数。
typedef struct gzFile_s *gzFile; /* 半透明的gzip文件描述符 */
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
打开一个gzip(.gz)文件进行读/写。mode参数和fopen一样("rb"或" wb"),但也可以包括压缩级别如"wb9";或者一个策略,如"f"作为过滤数据"wb6f","h"是huffman压缩"wb1h","R"是行程编码"wb1R",
"F"是固定编码压缩"wb9F"(关于压缩策略可参看deflateInit2的描述);如果mode为"T",将指定透明的写或附加操作,没有压缩,也不使用gzip格式。可见gzopen可用于读一个没有gzip格式的文件,这时gzread
直接从没有解压缩的文件中读数据。如果文件不能被打开或是没有足够的内存,gzopen将返回NULL。
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
用文件描述符来关联一个gzFile。文件描述符可通过open, dup, creat, pipe或fileno(如果文件之前已经用open打开了)之类的调用获取。mode参数与gzopen中类似。
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
设置本函数库用到内部缓冲区大小。默认大小为8192字节。本函数必须在gopen或gzdopen之后调用,在任何读或写文件之前调用,缓冲区内存分配总是会被推迟第一次读或写文件时。两个缓冲区被分配,要么两个缓冲区都使用这个设置值 ,要么一个使用这个设置值,另一个为这个值的两倍。一个更大的缓冲区大小,如64K或128K字节,将显著加快解压速度(读速度)。gzbuffer成功返回0,失败返回-1,例如调用得太晚。
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
动态更新压缩级别或策略。参数含义参看deflateInit2的描述。成功返回Z_OK,如果文件没有为写操作而打开,返回Z_STREAM_ERROR。
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
从压缩文件中读取给定大小的解压字节数。如果输入文件不是gzip格式,gzread直接复制指定定大小的字节数到缓冲区。返回实际读取的字节数,出错则返回-1。
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
写入给定大小的未解压数据到压缩文件中,返回实际写入的字节数,出错返回0。
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
在格式字符串的控制下转换、格式化或写入参数到压缩文件,这类似于fprintf。返回实际写入的字节数,出错则返回0。
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
写入给定的以null终止的字符串到压缩文件,写入时不包括末尾的null字符。返回实际写入的字符数,出错时返回-1。
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
从压缩文件中读取字节,直到len-1个字符被读取,或者一个换行字符被读取并传给buf,或者一个end-of-file条件被触发。如果各字符都读取完或者len==1,字符串最后将加上null字符。返回buf,如果出错则返回Z_NULL。
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
写入一个被转换成unsigned char的字符c到压缩文件,返回写入的字符,出错则返回-1。
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
从压缩文件中读取一个字节,返回这个字节。如果出错或文件到达末尾,返回-1。本函数实现为一个宏,以加快速度。
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
推回一个字符到原来的流中,这个字符即将在下一次读操作中作为首个被读取的字符。返回这个字符,出错则返回-1。
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
刷新所有挂起的输出到压缩文件。参数flush与deflate()中类似。返回值为zlib错误码(参看gzerror函数)。
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence));
设置压缩文件下一次gzread或gzwrite操作的开始位置。
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
重绕给定的文件,本函数只用于读操作,等价于(int)gzseek(file, 0L, SEEK_SET)。
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
如果end-of-file指示符被设置,返回true(1),否则返回0。
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
如果读取时内容被直接拷贝到缓冲区,返回1,否则返回0。
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
刷新所有挂起的输出,关闭压缩文件,释放所有的(de)compression状态。注意一旦文件被关闭,不能再调用gzerror,因为所有结构都被释放。在一个文件上不能调用gzclose多次,因为在一次分配上释放操作不能被调用多次。
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
返回在给定的压缩文件上发生的最后一次错误消息。
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
清除给定压缩文件的错误消息和end-of-file标志。
8、校验函数
这些函数和压缩是没有关系的,但是被公开是因为在应用序使用本压缩库时,他们可能是有用的。
(1)ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
用字节buf[0...len-1]更新一个运行的Adler-32校验和,返回这个新的CRC-32。如果buf为NULL,返回这个校验和需要的初始值。一个Adler-32校验和作为CRC32几乎是可靠的,但是计算起来更快。使用例子:
用字节buf[0...len-1]更新一个运行的CRC-32校验和,返回这个新的校验和。如果buf为NULL,返回这个CRC需要的初始值。使用例子:
alder32.c:计算数据流的Alder-32校验和,实现alder32()。
crc32.h和crc32.c:计算数据流的CRC-32,实现crc32()。
deflate.h和deflate.c:使用默认算法压缩数据,实现deflate函数簇。
inflate.h和inflate.c:zlib的解压,实现inflate函数簇。
compress.c:实现内存缓冲区的压缩,包括compress(), compress2(), compressBound()。
uncompr.c:实现内存缓冲区的解压,包括uncompress()。
gzguts.h和gzlib.c:读写gzip文件的通用实现,包括gzopen(), gzdopen(), gzbuffer(), gzrewind(), gzseek(), gztell(), gzoffset(), gzeof(), gzerror(), gzclearerr()。
gzclose.c:实现gzclose()。
gzread.c:读取gzip文件的实现,包括gzread(), gzgetc(), gzungetc(), gzgets(), gzdirect(), gzclose_r()。
gzwrite.c:写gzip文件的实现,包括gzwrite(), gzputc(), gzputs(), gzprintf(), gzflush(), gzsetparams(), gzclose_w()。
infback.c:使用回调接口实现解压,包括inflateBackInit(), inflateBack(), inflateBackEnd()。
zutil.h和zutil.c:zlib库用到的工具函数。包括zlibVersion(), zlibCompileFlags(), zError()。
zlib.h:zlib库导出的接口描述文件,应用程序使用zlib库时需要本文件。
zconf.h:zlib库的编译配置文件,如果编译时需要给所有库函数加上唯一的前缀,或者需要针对不同平台作特殊编译,需要用到本文件。还包括标准 C/C++兼容性定义;编译成DLL时是否使用WINAPI/WINAPIV调用方式;类型定义Byte,uInt, uLong, voidpf等。
inftrees.h和inftrees.c:为有效的解码生成Huffman树。
trees.h和trees.c:使用Huffman编码输出压缩的数据。
inffixed.h:使用固定编码压缩。
inffast.h和inffast.c:快速解压数据。
zlib是一套免费、通用、法律上不受限制的无损数据压缩库,可以在任何硬件及操作系统上使用。zlib数据格式可以跨平台移植。不像Unix compress(1)和GIF图像格式中使用的LZW压缩方法,当前zlib中使用的压缩算法不会扩充数据(LZW在极端情况下能使文件大小变为原来2 倍或3倍)。zlib的内存印迹也独立于输入数据,并且在压缩时能够被减小。zlib由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用抽象化的DEFLATE算法,最初是为libpng函数库所写的,后来普遍为许多软件所使用。此函数库为自由软件,使用zlib授权。
zlib授权是一个自由软件授权协议,但并非copyleft。协议原文在http://www.gzip.org/zlib /zlib_license.html。最新版本为1.2.2,2004年10月3日发布。版权持有人为Jean-loup Gailly和Mark Adler(1995-2004),类似于BSD许可。任何人都可以使用本软件,用于任何目的,包括闭源的商业应用。源码的修改和重新分发都是自由的,除了必须注明来源,并在发布的软件中保留此授权协议副本。
1、当前版本
#define ZLIB_VERSION "1.2.7"
#define ZLIB_VERNUM 0x1270
2、功能特性
zlib压缩库提供内存内压缩/解压缩函数。包括对解压数据完整性检查。这个版本只支持一种压缩方式(deflation),但是以后其他的算法也会被加入进来,并且保持同样的流接口。如果缓存区足够大,压缩被一次完成(例如输入文件被mmap了),否则就重复调用压缩。在后一种情况,程序必须在每次调用时提供更多的输入或更多输出空间。
本压缩库使用的默认压缩数据格式为zlib格式(在RFC 1950中描述),它是对deflate流(在RFC 1951中描述)的一种封装。本压缩库也支持对gzip(.gz)格式文件的读写操作,操作接口以"gz"开头,和stdio相似。gzip格式与 zlib格式不同,在RFC 1952中描述,是对deflate流的另一种封装。
本压缩库不安装任何信号处理器,解码器检查压缩数据的一致性,所以,即使在有损坏的输入情况下,本压缩库也不会崩溃。
(1)数据头
zlib能使用gzip数据头(header)、zlib数据头或者不使用数据头压缩数据。通常情况下,数据压缩使用zlib数据头,因为这提供错误数据检测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者知道压缩数据在什么地方结束。
gzip数据头比zlib数据头要大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件,但是它能够相当轻松的通过把压缩数据写入到一个有gzip文件头的文件中。
(2)算法
目前zlib仅支持一个LZ77的变种算法,即DEFLATE的算法。这个算法使用很少的系统资源,对各种数据提供很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。(尽管zip文件格式也支持几种其他的算法)。看起来zlib格式将不会被扩展使用任何其他算法,尽管数据头可以有这种可能性。
(3)使用资源
函式库提供了对处理器和内存使用控制的能力。不同的压缩级别数值可以指示不同的压缩执行速度。还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的。
(4)策略
压缩可以针对特定类型的数据进行优化。若使用者总是使用zlib压缩特定类型的数据,那么可以使用有针对性的策略可以提高压缩效率和性能。例如,如果使用者的数据包含很长的重复数据,那么可以用RLE(运行长度编码)策略,可能会有更好的结果。对于一般的数据,默认的策略是首选。
(5)错误处理
错误可以被发现和跳过,数据混乱可以被检测(只要数据和zlib或者gzip数据头一起被写入)。此外,如果全刷新点(full-flush points)被写入到压缩后的数据流中,那么错误数据是可以被跳过的,并且解压缩将重新同步到下个全刷新点(错误数据的无错恢复被提供)。全刷新点技术对于在不可靠的通道上的大数据流是很有用的,一些过去的数据丢失是不重要的(例如多媒体数据),但是建立太多的全刷新点会极大的影响速度和压缩。
(6)数据长度
对于压缩和解压缩,没有数据长度的限制。重复调用库函数允许处理无限的数据块。一些辅助代码(计数变量)可能会溢出,但是不影响实际的压缩和解压缩。当压缩一个长(无限)数据流时,最好写入全刷新点。
(7)使用zlib的软件
今天,zlib是一种事实上的业界标准,以至于在标准文档中,zlib和DEFLATE常常互换使用。数以千计的应用程序直接或间接依靠zlib压缩函式库(参考http://zlib.net/apps.html),包括:
Linux核心:使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。
libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。
Apache:使用zlib实作http 1.1。
OpenSSH、OpenSSL:以zlib达到最佳化加密网络传输。
FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。
rsync:以zlib最佳化远端同步时的传输。
Subversion 、Git和 CVS等版本控制系统:使用zlib来压缩和远端仓库的通讯流量。
dpkg和RPM等包管理软件:以zlib解压缩RPM或者其他封包。
另外,zlib被用在很多其他的编程语言中。在Java中可通过java.utl.zip使用zlib库;Python中通过import zlib使用zlib库;Perl的zlib接口可在CPAN找到;Tcl的zlib接口参看http://wiki.tcl.tk/4610。因为其代码的可移植性,宽松的授权许可以及较小的内存占用,zlib在许多嵌入式设备中也有应用。
3、流数据结构
- typedefvoidpf(*alloc_func)OF((voidpfopaque,uIntitems,uIntsize));
- typedefvoid(*free_func)OF((voidpfopaque,voidpfaddress));
- structinternal_state;
- typedefstructz_stream_s{
- z_constBytef*next_in;/*下一个输入字节*/
- uIntavail_in;/*next_in中可用的字节数*/
- uLongtotal_in;/*目前读取的输入总字节数*/
- Bytef*next_out;/*下一个输出字节应该放在这*/
- uIntavail_out;/*next_out中剩下的可用空间*/
- uLongtotal_out;/*目前输出的总字节数*/
- z_constchar*msg;/*最后的错误消息,如果没错误为NULL*/
- structinternal_stateFAR*state;/*对应用程序不可见*/
- alloc_funczalloc;/*用来分配内部状态*/
- free_funczfree;/*用来释放内部状态*/
- voidpfopaque;/*传给zalloc和zfree的私有数据对象*/
- intdata_type;/*数据类型的最好猜测:二进制数据或文本*/
- uLongadler;/*解压数据的adler32值*/
- uLongreserved;/*保留为将来使用*/
- }z_stream;
- typedefz_streamFAR*z_streamp;
- /*来自或传给zlib例程的gzip头部信息,对这些字段的含义,参考RFC1952*/
- typedefstructgz_header_s{
- inttext;/*为true,如果压缩数据被认为是文本*/
- uLongtime;/*修改时间*/
- intxflags;/*额外标志(写gzip文件时不会用到)*/
- intos;/*操作系统*/
- Bytef*extra;/*指向额外的字段,如果没有则为Z_NULL*/
- uIntextra_len;/*额外字段的长度(如果extrextra!=Z_NULL则有底)*/
- uIntextra_max;/*extra的空间上限(只用在读头部)*/
- Bytef*name;/*指向以0终止的文件名,或为Z_NULL*/
- uIntname_max;/*name的空间上限(只用在读头部)*/
- Bytef*comment;/*指向以0终止的注释,或为Z_NULL*/
- uIntcomm_max;/*comment的空间上限(只用在读头部)*/
- inthcrc;/*为true,如果会有头部CRC*/
- intdone;/*为true,当gzip头部读取完时(写gzip文件时不会用到)*/
- }gz_header;
- typedefgz_headerFAR*gz_headerp;
typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); typedef void (*free_func) OF((voidpf opaque, voidpf address)); struct internal_state; typedef struct z_stream_s { z_const Bytef *next_in; /* 下一个输入字节 */ uInt avail_in; /* next_in中可用的字节数 */ uLong total_in; /* 目前读取的输入总字节数 */ Bytef *next_out; /* 下一个输出字节应该放在这 */ uInt avail_out; /* next_out中剩下的可用空间 */ uLong total_out; /* 目前输出的总字节数 */ z_const char *msg; /* 最后的错误消息,如果没错误为NULL */ struct internal_state FAR *state; /* 对应用程序不可见 */ alloc_func zalloc; /* 用来分配内部状态 */ free_func zfree; /* 用来释放内部状态 */ voidpf opaque; /* 传给zalloc和zfree的私有数据对象 */ int data_type; /* 数据类型的最好猜测:二进制数据或文本 */ uLong adler; /* 解压数据的adler32值 */ uLong reserved; /* 保留为将来使用 */ } z_stream; typedef z_stream FAR *z_streamp; /* 来自或传给zlib例程的gzip头部信息,对这些字段的含义,参考RFC 1952 */ typedef struct gz_header_s { int text; /* 为true,如果压缩数据被认为是文本 */ uLong time; /* 修改时间 */ int xflags; /* 额外标志(写gzip文件时不会用到) */ int os; /* 操作系统 */ Bytef *extra; /* 指向额外的字段,如果没有则为Z_NULL */ uInt extra_len; /* 额外字段的长度(如果extrextra != Z_NULL则有底) */ uInt extra_max; /* extra的空间上限(只用在读头部) */ Bytef *name; /* 指向以0终止的文件名,或为Z_NULL */ uInt name_max; /* name的空间上限(只用在读头部) */ Bytef *comment; /* 指向以0终止的注释,或为Z_NULL */ uInt comm_max; /* comment的空间上限(只用在读头部) */ int hcrc; /* 为true,如果会有头部CRC */ int done; /* 为true,当gzip头部读取完时(写gzip文件时不会用到) */ } gz_header; typedef gz_header FAR *gz_headerp;当avail_in变成0时,应用程序必须更新next_int和avail_in。当avail_out变成0时,还必须更新next_out和 avail_out。应用程序在调用init函数之前必须初始化zalloc,zfree和opaque。除此,其他的所有被压缩库设置的字段都不能被应用程序修改。应用程序提供的opaque值将作为调用时传给zalloc和zfree的第一个参数,这在用户内存管理里有用。opaque值对压缩库本身并没有什么意义。如果对象没有足够的内存,zalloc必须返回Z_NULL。如果zlib被用在多线程环境中,zalloc和zfree必须是线程安全的。
在16-bit系统上,函数zalloc和zfree必须能够分配精确的65536字节,但如果定义了符号MAXSEG_64K(参看 zconf.h),则并不需要分配比这更多的空间。在MSDOS上,zalloc返回的65536字节对象的指针必须把偏移规格化为0,默认的分配函数会保证这一点(参看zutil.c)。为了减少内存需求,并且避免64K对象的分配,可以带-DMAX_WBITS=14编译参数(参看zconf.h)来编译zlib库,这样会牺牲一点压缩率。
字段total_in和total_out可用于统计和进程报告。在压缩后,total_in表示解压数据总大小,它可以被解压工具使用,特别是如果解压工具想一步之内解压所有的数据。
4、常量
- /*允许的flush值,更多细节参看下面的deflate()和inflate()*/
- #defineZ_NO_FLUSH0
- #defineZ_PARTIAL_FLUSH1
- #defineZ_SYNC_FLUSH2
- #defineZ_FULL_FLUSH3
- #defineZ_FINISH4
- #defineZ_BLOCK5
- #defineZ_TREES6
- /*压缩、解压函数的返回码,负数表示错误,正数表示正常事件*/
- #defineZ_OK0
- #defineZ_STREAM_END1
- #defineZ_NEED_DICT2
- #defineZ_ERRNO(-1)
- #defineZ_STREAM_ERROR(-2)
- #defineZ_DATA_ERROR(-3)
- #defineZ_MEM_ERROR(-4)
- #defineZ_BUF_ERROR(-5)
- #defineZ_VERSION_ERROR(-6)
- /*压缩级别*/
- #defineZ_NO_COMPRESSION0
- #defineZ_BEST_SPEED1
- #defineZ_BEST_COMPRESSION9
- #defineZ_DEFAULT_COMPRESSION(-1)
- /*压缩策略,细节参看下面的deflateInit2()*/
- #defineZ_FILTERED1
- #defineZ_HUFFMAN_ONLY2
- #defineZ_RLE3
- #defineZ_FIXED4
- #defineZ_DEFAULT_STRATEGY0
- /*data_type字段可能的值(参看inflate())*/
- #defineZ_BINARY0
- #defineZ_TEXT1
- #defineZ_ASCIIZ_TEXT/*为了兼容1.2.2和更早的版本*/
- #defineZ_UNKNOWN2
- /*deflate压缩方式(这个版本支持的唯一压缩方式)*/
- #defineZ_DEFLATED8
- defineZ_NULL0/*为了初始化zalloc,zfree,opaque*/
- /*为了兼容小于1.0.2的版本*/
- #definezlib_versionzlibVersion()
/* 允许的flush值,更多细节参看下面的deflate()和inflate() */ #define Z_NO_FLUSH 0 #define Z_PARTIAL_FLUSH 1 #define Z_SYNC_FLUSH 2 #define Z_FULL_FLUSH 3 #define Z_FINISH 4 #define Z_BLOCK 5 #define Z_TREES 6 /* 压缩、解压函数的返回码,负数表示错误,正数表示正常事件 */ #define Z_OK 0 #define Z_STREAM_END 1 #define Z_NEED_DICT 2 #define Z_ERRNO (-1) #define Z_STREAM_ERROR (-2) #define Z_DATA_ERROR (-3) #define Z_MEM_ERROR (-4) #define Z_BUF_ERROR (-5) #define Z_VERSION_ERROR (-6) /* 压缩级别 */ #define Z_NO_COMPRESSION 0 #define Z_BEST_SPEED 1 #define Z_BEST_COMPRESSION 9 #define Z_DEFAULT_COMPRESSION (-1) /* 压缩策略,细节参看下面的deflateInit2() */ #define Z_FILTERED 1 #define Z_HUFFMAN_ONLY 2 #define Z_RLE 3 #define Z_FIXED 4 #define Z_DEFAULT_STRATEGY 0 /* data_type字段可能的值(参看inflate()) */ #define Z_BINARY 0 #define Z_TEXT 1 #define Z_ASCII Z_TEXT /* 为了兼容1.2.2和更早的版本 */ #define Z_UNKNOWN 2 /* deflate压缩方式(这个版本支持的唯一压缩方式) */ #define Z_DEFLATED 8 define Z_NULL 0 /* 为了初始化zalloc, zfree, opaque */ /* 为了兼容小于1.0.2的版本 */ #define zlib_version zlibVersion()5、基本函数
(1)ZEXTERN const char * ZEXPORT zlibVersion OF((void));
应用程序会比较zlibVersion和ZLIB_VERSION的一致性。如果第一个字不同,说明zlib和应用程序使用的zlib.h是不一致的。这个检查将被defalteInit和infalteInit自动调用。
(2)ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level));
为压缩初始化内部流的状态。字段zalloc, zfree和opaque必须在调用之前初始化。如果zalloc和zfree被设为Z_NULL,deflateInit用默认分配函数来更新它们。压缩级别必须是define Z_DEFAULT_COMPRESSION,或者0到9之间,1为最快速度,9为最好的压缩率,0表示不作任何压缩(输入数据简单地被拷贝成一块)。 Z_DEFAULT_COMPRESSION为默认压缩级别,它在速度和压缩率之间取一个折衷(当前等于级别6)。函数成功时返回Z_OK,否则返回相应的错误码(Z_MEM_ERROR, Z_STREAM_ERROR或Z_VERSION_ERROR)。deflateInit不执行任何压缩动作,压缩动作由deflate()来执行。
(3)ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush));
压缩尽可能多的数据,直到输入缓冲区变空或输出缓冲区变满。它可能引入一些输出延迟(读取输入但不产生任何输出),除非强制刷新缓冲区。本函数执行以下一个或两个动作:
* 压缩从next_in开始的输入数据,并且更新相应的next_in和avail_in。如果不能处理所有的输入(因为输出缓冲区已满),next_in和avail_in会作相应更新,并且下一次调用deflate()时在这个点处恢复执行。
* 生成从next_out开始的输出,并且更新相应的next_out和avail_out。如果参数flush为非零,则本行为强制执行。强制频繁地刷新会降低压缩率,因此这个参数应该只在必要时才设置(在交互式应用程序中)。有些输出即使flush没有被设置也会生成。
(4)ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm));
所有为当前流分配的动态数据结构被释放。本函数抛弃任何未处理的输入,并且不会刷新任何挂起的输出。成功时返回Z_OK,流状态不一致时返回 Z_STREAM_ERROR,流过早被释放时(一些输入或输出被抛弃了)返回Z_DATA_ERROR。在错误情形中,msg信息可能被设置,然后指向一个静态字符串。
(5)ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm));
为解压初始化内部流状态。字段next_in, avail_in, zalloc, zfree和opaque必须在调用之前初始化。如果next_in不等于Z_NULL且avail_in足够大(准确的值取决于压缩方式),inflateInit从zlib头部确定压缩方式,然后分配所有数据结构。否则分配将会被推迟到第一次调用inflate。如果zalloc和 zfree被设为Z_NULL,inflateInit用默认分配函数来更新它们。函数返回 Z_OK,Z_MEM_ERROR,Z_VERSION_ERROR或Z_STREAM_ERROR。
(6)ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
解压尽可能多的数据。直到输入缓冲区变空或输出缓冲区变满。它可能引入一些输出延迟(读取输入但不产生任何输出),除非强制刷新缓冲区。本函数执行以下一个或两个动作:
* 解压从next_in开始的输入数据,并且更新相应的next_in和avail_in。如果不能处理所有的输入(因为输出缓冲区已满),next_in会作相应更新,并且下一次调用inflate()时在这个点处恢复执行。
* 生成从next_out开始的输出,并且更新相应的next_out和avail_out。inflate()生成尽可能多的输出,直到没有更多的输入或者输出缓冲区已满。flush参数可以是Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH,Z_BLOCK或Z_TREES。
(7)ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm));
所有为这个stream动态分派的数据结构在这被释放。 这个函数丢弃所有未处理的输入,并且不会刷新任何挂起的输出。如果成功,inflateEnd返回Z_OK;如果stream是不一致的,返回 Z_STREAM_ERROR,在错误情形中,msg信息可能被设置,然后指向一个静态字符串。
6、高级函数
以下函数用于一些特殊的应用中:
ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, int level, int method, int windowBits, int memLevel, int strategy));
ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength));
ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, z_streamp source));
ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, int level, int strategy));
ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, int good_length, int max_lazy, int nice_length, int max_chain));
ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, uLong sourceLen));
ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, unsigned *pending, int *bits));
ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, int bits, int value));
ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, gz_headerp head));
ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, int windowBits));
ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, const Bytef *dictionary, uInt dictLength));
ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, z_streamp source));
ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, int windowBits));
ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, int bits, int value));
ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm));
ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, gz_headerp head));
ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, unsigned char FAR *window));
ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, in_func in, void FAR *in_desc, out_func out, void FAR *out_desc));
ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm));
ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void));
7、实用函数
以下实用函数的实现建立在前面介绍的基本面向流的函数上。为了简化接口,设置了一些默认选项(压缩级别,内存使用,标准内存分配器功能)这些实用函数的源代码很容易被修改,如果你要实现一些特殊选项。
(1)ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
压缩source buffer到destination buffer。sourceLen是source buffer的长度(byte)。调用前,destLen是destination buffer的总共长度(byte),它必须至少是compressBound(sourceLen)的返回值,一般为sourceLen长度的0.1% 再加上12个byte。退出前,destLen是实际的compressed buffer长度。如果输入文件是mmap的,这个函数可以一次压缩整个文件。如果压缩成功返回Z_OK, 如果没有足够的内存返回Z_MEM_ERROR,如果输出缓冲区中没有足够的空间返回Z_BUF_ERROR。
(2)ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen, int level));
与compress功能一样,只不过多了一个level参数。参数level为压缩级别,与defalteInit中的含义一样。如果level是无效的,返回Z_STREAM_ERROR。
(3)ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen));
返回compressed size的上限,在sourceLen个字节上执行copress()或compress2()后。在调用compress()或compress2() 分配destination buffer之前,本函数可用于计算的destLen。
(4)ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen));
解压source buffer到destination buffer。sourceLen是source buffer的长度(byte)。调用前,destLen是destination buffer的总共长度(byte),它必须足够大以容纳全部解压后的数据(解压后的数据大小必须在先前由压缩工具保存好,然后通过一些机制传给解压工具,这种机制不在本压缩库的讨论范围内)。退出前,destLen是实际的compressed buffer长度。如果输入文件是mmap的,这个函数可以一次解压整个文件。如果解压成功返回Z_OK,如果没有足够的内存返回 Z_MEM_ERROR,如果输出缓冲区中没有足够的空间返回Z_BUF_ERROR,如果输入数据有损坏返回Z_DATA_ERROR。在没有足够空间的情况下,uncompress()用解压数据填充输出缓冲区,直到空间末尾为上。
(5)下面是gzip文件访问函数。
typedef struct gzFile_s *gzFile; /* 半透明的gzip文件描述符 */
ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode));
打开一个gzip(.gz)文件进行读/写。mode参数和fopen一样("rb"或" wb"),但也可以包括压缩级别如"wb9";或者一个策略,如"f"作为过滤数据"wb6f","h"是huffman压缩"wb1h","R"是行程编码"wb1R",
"F"是固定编码压缩"wb9F"(关于压缩策略可参看deflateInit2的描述);如果mode为"T",将指定透明的写或附加操作,没有压缩,也不使用gzip格式。可见gzopen可用于读一个没有gzip格式的文件,这时gzread
直接从没有解压缩的文件中读数据。如果文件不能被打开或是没有足够的内存,gzopen将返回NULL。
ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode));
用文件描述符来关联一个gzFile。文件描述符可通过open, dup, creat, pipe或fileno(如果文件之前已经用open打开了)之类的调用获取。mode参数与gzopen中类似。
ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size));
设置本函数库用到内部缓冲区大小。默认大小为8192字节。本函数必须在gopen或gzdopen之后调用,在任何读或写文件之前调用,缓冲区内存分配总是会被推迟第一次读或写文件时。两个缓冲区被分配,要么两个缓冲区都使用这个设置值 ,要么一个使用这个设置值,另一个为这个值的两倍。一个更大的缓冲区大小,如64K或128K字节,将显著加快解压速度(读速度)。gzbuffer成功返回0,失败返回-1,例如调用得太晚。
ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy));
动态更新压缩级别或策略。参数含义参看deflateInit2的描述。成功返回Z_OK,如果文件没有为写操作而打开,返回Z_STREAM_ERROR。
ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len));
从压缩文件中读取给定大小的解压字节数。如果输入文件不是gzip格式,gzread直接复制指定定大小的字节数到缓冲区。返回实际读取的字节数,出错则返回-1。
ZEXTERN int ZEXPORT gzwrite OF((gzFile file, voidpc buf, unsigned len));
写入给定大小的未解压数据到压缩文件中,返回实际写入的字节数,出错返回0。
ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...));
在格式字符串的控制下转换、格式化或写入参数到压缩文件,这类似于fprintf。返回实际写入的字节数,出错则返回0。
ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s));
写入给定的以null终止的字符串到压缩文件,写入时不包括末尾的null字符。返回实际写入的字符数,出错时返回-1。
ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len));
从压缩文件中读取字节,直到len-1个字符被读取,或者一个换行字符被读取并传给buf,或者一个end-of-file条件被触发。如果各字符都读取完或者len==1,字符串最后将加上null字符。返回buf,如果出错则返回Z_NULL。
ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c));
写入一个被转换成unsigned char的字符c到压缩文件,返回写入的字符,出错则返回-1。
ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
从压缩文件中读取一个字节,返回这个字节。如果出错或文件到达末尾,返回-1。本函数实现为一个宏,以加快速度。
ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file));
推回一个字符到原来的流中,这个字符即将在下一次读操作中作为首个被读取的字符。返回这个字符,出错则返回-1。
ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush));
刷新所有挂起的输出到压缩文件。参数flush与deflate()中类似。返回值为zlib错误码(参看gzerror函数)。
ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, z_off_t offset, int whence));
设置压缩文件下一次gzread或gzwrite操作的开始位置。
ZEXTERN int ZEXPORT gzrewind OF((gzFile file));
重绕给定的文件,本函数只用于读操作,等价于(int)gzseek(file, 0L, SEEK_SET)。
ZEXTERN int ZEXPORT gzeof OF((gzFile file));
如果end-of-file指示符被设置,返回true(1),否则返回0。
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
如果读取时内容被直接拷贝到缓冲区,返回1,否则返回0。
ZEXTERN int ZEXPORT gzclose OF((gzFile file));
刷新所有挂起的输出,关闭压缩文件,释放所有的(de)compression状态。注意一旦文件被关闭,不能再调用gzerror,因为所有结构都被释放。在一个文件上不能调用gzclose多次,因为在一次分配上释放操作不能被调用多次。
ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum));
返回在给定的压缩文件上发生的最后一次错误消息。
ZEXTERN void ZEXPORT gzclearerr OF((gzFile file));
清除给定压缩文件的错误消息和end-of-file标志。
8、校验函数
这些函数和压缩是没有关系的,但是被公开是因为在应用序使用本压缩库时,他们可能是有用的。
(1)ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
用字节buf[0...len-1]更新一个运行的Adler-32校验和,返回这个新的CRC-32。如果buf为NULL,返回这个校验和需要的初始值。一个Adler-32校验和作为CRC32几乎是可靠的,但是计算起来更快。使用例子:
- uLongadler=adler32(0L,Z_NULL,0);
- while(read_buffer(buffer,length)!=EOF){
- adler=adler32(adler,buffer,length);
- }
- if(adler!=original_adler)error();
uLong adler = adler32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { adler = adler32(adler, buffer, length); } if (adler != original_adler) error();(2)ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
用字节buf[0...len-1]更新一个运行的CRC-32校验和,返回这个新的校验和。如果buf为NULL,返回这个CRC需要的初始值。使用例子:
- uLongcrc=crc32(0L,Z_NULL,0);
- while(read_buffer(buffer,length)!=EOF){
- crc=crc32(crc,buffer,length);
- }
- if(crc!=original_crc)error();
uLong crc = crc32(0L, Z_NULL, 0); while (read_buffer(buffer, length) != EOF) { crc = crc32(crc, buffer, length); } if (crc != original_crc) error();9、文件概览
alder32.c:计算数据流的Alder-32校验和,实现alder32()。
crc32.h和crc32.c:计算数据流的CRC-32,实现crc32()。
deflate.h和deflate.c:使用默认算法压缩数据,实现deflate函数簇。
inflate.h和inflate.c:zlib的解压,实现inflate函数簇。
compress.c:实现内存缓冲区的压缩,包括compress(), compress2(), compressBound()。
uncompr.c:实现内存缓冲区的解压,包括uncompress()。
gzguts.h和gzlib.c:读写gzip文件的通用实现,包括gzopen(), gzdopen(), gzbuffer(), gzrewind(), gzseek(), gztell(), gzoffset(), gzeof(), gzerror(), gzclearerr()。
gzclose.c:实现gzclose()。
gzread.c:读取gzip文件的实现,包括gzread(), gzgetc(), gzungetc(), gzgets(), gzdirect(), gzclose_r()。
gzwrite.c:写gzip文件的实现,包括gzwrite(), gzputc(), gzputs(), gzprintf(), gzflush(), gzsetparams(), gzclose_w()。
infback.c:使用回调接口实现解压,包括inflateBackInit(), inflateBack(), inflateBackEnd()。
zutil.h和zutil.c:zlib库用到的工具函数。包括zlibVersion(), zlibCompileFlags(), zError()。
zlib.h:zlib库导出的接口描述文件,应用程序使用zlib库时需要本文件。
zconf.h:zlib库的编译配置文件,如果编译时需要给所有库函数加上唯一的前缀,或者需要针对不同平台作特殊编译,需要用到本文件。还包括标准 C/C++兼容性定义;编译成DLL时是否使用WINAPI/WINAPIV调用方式;类型定义Byte,uInt, uLong, voidpf等。
inftrees.h和inftrees.c:为有效的解码生成Huffman树。
trees.h和trees.c:使用Huffman编码输出压缩的数据。
inffixed.h:使用固定编码压缩。
inffast.h和inffast.c:快速解压数据。
相关推荐
### Python标准库中文版知识点概览 #### 0. 关于本书 - **目标与定位**:本书旨在全面介绍Python标准库,为Python开发者提供一个系统性的资源来学习和掌握Python标准库中的各种模块。 - **适用人群**:无论是...
#### 一、标准库概览 Go语言标准库是Go编程语言的一个核心组成部分,它包含了一系列预定义的包和工具,旨在帮助开发者快速构建高效的应用程序。Go语言标准库非常全面,涵盖了网络编程、文件处理、并发控制等多个方面...
- 对于Windows用户,可以利用Visual Studio创建项目,将Anubis和zlib库的源代码导入,配置包含目录,然后编译生成exe文件。 **软件配置和使用** Anubis通过命令行参数运行,用户需要指定输入的XML配置文件、输出...
本文重点介绍的是`zlib`模块,它基于ZLIB库实现,并且提供了对ZLIB格式文件的支持。 #### zlib模块简介 `zlib`模块是Python的一个内置模块,提供了一系列函数和类来处理ZLIB格式的数据压缩。ZLIB是一种通用的压缩...
### PyInstaller 手册知识点概览 #### 一、引言 PyInstaller 是一个将 Python 程序打包成独立可执行文件的工具,适用于 Windows、Linux 和 MacOS X 平台。它支持从简单的脚本到复杂的包结构,并且能够处理大多数...
#### MongoDB 3.0 新特性概览 MongoDB 3.0 是在2015年3月3日正式发布的,与之前的2.0版本相比,它引入了大量的新功能和技术改进。其中最重要的一个特性就是加入了新的存储引擎——WiredTiger,而默认使用的存储引擎...
- **《TCPIP详解卷1:协议原书第2版》**:详细介绍TCP/IP协议栈的工作原理和技术细节。 - **《TCPIP协议族(第4版)》**:对TCP/IP协议族进行全面且深入的讲解。 - **《图解TCP_IP_第5版》**:通过图表形式生动解释TCP...
- **依赖库**:通常还需要先安装pcre和zlib库,前者用于支持Nginx的rewrite功能,后者则用于压缩功能。 ##### 2.2 正式安装 - **编译参数**:在正式开始编译之前,需要准备好相应的编译参数,这些参数可能包括启用...
### Python标准库简介 Python标准库是一系列内置的模块集合,为Python开发人员提供了丰富的功能。这些模块可以处理从简单的文本操作到复杂的网络通信等各种任务。对于初学者来说,掌握Python标准库的基本用法是非常...
go/*系列包,如go/ast、go/build、go/parser等,提供了与Go语言源代码处理相关的功能,例如源代码抽象语法树的遍历、构建、格式化等操作,是实现编译器、代码分析工具的重要组成部分。 ### 结语 以上介绍的包只是Go...
### Python标准库概述 Python标准库是一系列内置模块与包的集合,为Python开发者提供了丰富的功能,涵盖了从基本数据操作到复杂网络应用的各种需求。在本篇内容中,我们将详细介绍Python标准库2.6版本中的一些核心...
2. **安装依赖项**:使用`sudo apt-get install libdumbnet1 libnet1-dev libpcap0.8-dev flex bison make gcc g++ autoconf automake libtool zlib1g-dev dpkg-dev`命令安装Snort所需的所有依赖库。 3. **下载...
#### 背景与需求分析 Hadoop作为大数据处理领域的领头羊,其MapReduce框架凭借分布式处理能力,为海量数据提供了高效的解决方案。然而,在大规模的数据处理场景下,尤其是当map和reduce任务数量激增至数万个时,...
使用`yum install`命令安装一系列必要的开发库和工具,这些工具包括但不限于zlib-devel、bzip2-devel、openssl-devel等。 ```bash [root@reportweb]# yum install zlib-devel bzip2-devel openssl-devel ncurses-...