宜兴通达竭诚为您服务。

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

2016-12-27 03:12:00     作者: Administrator     来源:互联网,版权归作者所有     浏览次数: 365     文字大小:【】【】【

本文整理自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、流数据结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
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、常量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/* 允许的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、高级函数

   以下函数用于一些特殊的应用中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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几乎是可靠的,但是计算起来更快。使用例子:

1
2
3
4
5
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需要的初始值。使用例子:

1
2
3
4
5
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:快速解压数据。

相关文章 评论

服务原则及地区范围

宜兴通达团队,在企业网络维护和企业信息化建设与咨询方面,有10多年经验。

我团队愿与客户一道,力求彻底解决客户问题!
我们不是在给企业提供“头痛医头、脚痛医脚”的暂时解决方案,而是在部署根本性安全与稳定服务!!
我们愿携手客户,建立企业IT规划;杜绝随意安装系统、软件等操作;力求共同维护有序、安全、稳定的网络办公环境!!!
IT服务,服务是根本,客户是上帝;我们提供快速响应、快速上门、快速排查,提供优质高效的服务!!!!

通达团队提供全国范围内的服务,服务形式包括远程协助、电话咨询、电子邮件咨询、传真咨询、问答平台的问题解决等。

宜兴地区提供上门服务:

  • 市区服务:宜城街道、城北街道(屺亭街道)、新街街道、新庄街道、环科园、渚桥开发区
  • 市郊服务:张渚镇、西渚镇、太华镇、徐舍镇、官林镇、杨巷镇、新建镇、和桥镇、高塍镇、万石镇、周铁镇、芳桥镇、丁蜀镇、湖父镇。
  • 联系电话:189-21-343434
  • 在线沟通: