zlib库剖析(1):实现概览

来源:互联网 发布:网上棋牌游戏作弊软件 编辑:程序博客网 时间:2024/05/15 05:38
本文整理自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在许多嵌入式设备中也有应用。    

    3、流数据结构

[cpp] view plaincopyprint?
  1. typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size));  
  2. typedef void   (*free_func)  OF((voidpf opaque, voidpf address));  
  3.   
  4. struct internal_state;  
  5.   
  6. typedef struct z_stream_s {  
  7.     z_const Bytef *next_in;     /* 下一个输入字节 */  
  8.     uInt     avail_in;  /* next_in中可用的字节数 */  
  9.     uLong    total_in;  /* 目前读取的输入总字节数 */  
  10.   
  11.     Bytef    *next_out; /* 下一个输出字节应该放在这 */  
  12.     uInt     avail_out; /* next_out中剩下的可用空间 */  
  13.     uLong    total_out; /* 目前输出的总字节数 */  
  14.   
  15.     z_const char *msg;  /* 最后的错误消息,如果没错误为NULL */  
  16.     struct internal_state FAR *state; /* 对应用程序不可见 */  
  17.   
  18.     alloc_func zalloc;  /* 用来分配内部状态 */  
  19.     free_func  zfree;   /* 用来释放内部状态 */  
  20.     voidpf     opaque;  /* 传给zalloc和zfree的私有数据对象 */  
  21.   
  22.     int     data_type;  /* 数据类型的最好猜测:二进制数据或文本 */  
  23.     uLong   adler;      /* 解压数据的adler32值 */  
  24.     uLong   reserved;   /* 保留为将来使用 */  
  25. } z_stream;  
  26.   
  27. typedef z_stream FAR *z_streamp;  
  28. /* 来自或传给zlib例程的gzip头部信息,对这些字段的含义,参考RFC 1952 */  
  29. typedef struct gz_header_s {  
  30.     int     text;       /* 为true,如果压缩数据被认为是文本 */  
  31.     uLong   time;       /* 修改时间 */  
  32.     int     xflags;     /* 额外标志(写gzip文件时不会用到) */  
  33.     int     os;         /* 操作系统 */  
  34.     Bytef   *extra;     /* 指向额外的字段,如果没有则为Z_NULL */  
  35.     uInt    extra_len;  /* 额外字段的长度(如果extrextra != Z_NULL则有底) */  
  36.     uInt    extra_max;  /* extra的空间上限(只用在读头部) */  
  37.     Bytef   *name;      /* 指向以0终止的文件名,或为Z_NULL */  
  38.     uInt    name_max;   /* name的空间上限(只用在读头部) */  
  39.     Bytef   *comment;   /* 指向以0终止的注释,或为Z_NULL */  
  40.     uInt    comm_max;   /* comment的空间上限(只用在读头部) */  
  41.     int     hcrc;       /* 为true,如果会有头部CRC */  
  42.     int     done;       /* 为true,当gzip头部读取完时(写gzip文件时不会用到) */  
  43. } gz_header;  
  44.   
  45. 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、常量
[cpp] view plaincopyprint?
  1. /* 允许的flush值,更多细节参看下面的deflate()和inflate() */  
  2. #define Z_NO_FLUSH      0   
  3. #define Z_PARTIAL_FLUSH 1  
  4. #define Z_SYNC_FLUSH    2   
  5. #define Z_FULL_FLUSH    3  
  6. #define Z_FINISH        4   
  7. #define Z_BLOCK         5  
  8. #define Z_TREES         6   
  9.   
  10. /* 压缩、解压函数的返回码,负数表示错误,正数表示正常事件 */  
  11. #define Z_OK            0  
  12. #define Z_STREAM_END    1   
  13. #define Z_NEED_DICT     2  
  14. #define Z_ERRNO        (-1)   
  15. #define Z_STREAM_ERROR (-2)  
  16. #define Z_DATA_ERROR   (-3)   
  17. #define Z_MEM_ERROR    (-4)  
  18. #define Z_BUF_ERROR    (-5)   
  19. #define Z_VERSION_ERROR (-6)  
  20.   
  21. /* 压缩级别 */  
  22. #define Z_NO_COMPRESSION         0   
  23. #define Z_BEST_SPEED             1  
  24. #define Z_BEST_COMPRESSION       9   
  25. #define Z_DEFAULT_COMPRESSION  (-1)  
  26.   
  27. /* 压缩策略,细节参看下面的deflateInit2() */  
  28. #define Z_FILTERED            1   
  29. #define Z_HUFFMAN_ONLY        2  
  30. #define Z_RLE                 3   
  31. #define Z_FIXED               4  
  32. #define Z_DEFAULT_STRATEGY    0   
  33.   
  34. /* data_type字段可能的值(参看inflate()) */  
  35. #define Z_BINARY   0   
  36. #define Z_TEXT     1   
  37. #define Z_ASCII    Z_TEXT   /* 为了兼容1.2.2和更早的版本 */  
  38. #define Z_UNKNOWN  2   
  39.   
  40. /* deflate压缩方式(这个版本支持的唯一压缩方式) */  
  41. #define Z_DEFLATED   8   
  42.   
  43. define Z_NULL  0  /* 为了初始化zalloc, zfree, opaque */  
  44.   
  45. /* 为了兼容小于1.0.2的版本 */  
  46. #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几乎是可靠的,但是计算起来更快。使用例子:

[cpp] view plaincopyprint?
  1. uLong adler = adler32(0L, Z_NULL, 0);  
  2. while (read_buffer(buffer, length) != EOF) {  
  3.     adler = adler32(adler, buffer, length);  
  4. }  
  5. 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需要的初始值。使用例子:
[cpp] view plaincopyprint?
  1. uLong crc = crc32(0L, Z_NULL, 0);  
  2. while (read_buffer(buffer, length) != EOF) {  
  3.     crc = crc32(crc, buffer, length);  
  4. }  
  5. 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:快速解压数据。