zlib 适用于数据压缩的函式库,由Jean-loup Gailly (负责compression)和 Mark Adler (负责decompression)开发。
zlib被设计成一个免费的、通用的、法律上不受阻碍(即没有被任何专利覆盖) 的无损数据压缩库。zlib几乎适用于任何计算器硬件和操作系统。
zlib本身的数据格式可以进行跨平台的移植。 与在Unix上适用的LZW压缩方法 以及 GIF 图像压缩不同, zlib中适用的压缩方法从不对数据进行拓展。(LZW在极端情况下会导致文件大小变为原来的两倍、甚至三倍)。zlib的内存占用也是独立于输入数据的,并且在必要的情况下可以适当减少部分内存占用。
首先, 下载zlib, 当前最新的 版本应该是1.2.8. 并解压
windeal@ubuntu:opensource$ wget https://sourceforge.net/projects/libpng/files/zlib/1.2.8/zlib-1.2.8.tar.gz/download -o zlib-1.2.8.tar.gz
windeal@ubuntu:opensource$ tar zvfx zlib-1.2.8.tar.gz
进入zlib目录,执行以下命令安装zlib
windeal@ubuntu:zlib-1.2.8$ ./configure
windeal@ubuntu:zlib-1.2.8$ make
windeal@ubuntu:zlib-1.2.8$ make check
windeal@ubuntu:zlib-1.2.8$ sudo make install
在make install
这一步,由于要把zlib安装到/usr/local/lib
路径下,所以可能需要root
权限。
安装成功后,可以在/usr/local/lib
下找到 libz.a
。
libz.a是一个静态库,为了使用zlib的接口,我们必须在连接我们的程序时,libz.a链接进来。
只需在 链接命令后加-lz /usr/llocal/lib/libz.a
即可。
举个例子, 我们有一个使用zlib库的应用程序, 源文件只有一个:zpipe.c
, 里面调用了zlib的接口,这时执行以下命令编译既可:
windeal@ubuntu:examples$ gcc -o zpipe.o -c zpipe.c
windeal@ubuntu:examples$ gcc -o zpipe zpipe.o -lz /usr/local/lib/libz.a
zlib 提供了一系列用于压缩和解压的函数接口, 具体的含义可以参考zlib manual
zlib 在 examples 路径下提供了许多使用zlib的例子:
windeal@ubuntu:examples$ ls
enough.c fitblk.c gun.c gzappend.c gzjoin.c gzlog.c gzlog.h README.examples zlib_how.html zpipe.c zran.c
windeal@ubuntu:examples$
在README.examples
有介绍各个example的作用。
这些例子已经大概说明了zlib的基本用法。
##3.1 compress 与 uncompress
compress
和uncompress
是zlib最基本的两个函数了。他们分别用于压缩和解压数据。 原型如下:
ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen,
const Bytef *source, uLong sourceLen));
参数类型Bytef
表示字节流,它与字符串有所不同,字节流没有结束符,因而需要配备长度信息,处理字符串的时候需要把结束符也当成一个普通的字节。 而uLongf
则用于指明长度信息了, 其实相当于unsigned long
。
看下面的例子:
#include
#include
#include
#include
int main(int argc, char *argv[])
{
char inbuf[] = "Hello, This is a demo for compress and uncompress interface!\n"
"Written by windeal.li\n"
"email: [email protected]\n";
uLong inlen = sizeof(inbuf);
char *outbuf = NULL;
uLong outlen;
outlen = compressBound(inlen);
printf("in_len: %ld\n", inlen);
printf("out_len: %ld\n", outlen);
if ((outbuf = (char *)malloc(sizeof(char) * outlen)) == NULL){
fprintf(stderr, "Failed to malloc memory for outbuf!\n");
return -1;
}
/* compress */
if (compress(outbuf, &outlen, inbuf, inlen) != Z_OK) {
fprintf(stderr, "Compress failed!\n");
return -1;
}
printf("Compress Sucess!\n");
printf("\routlen:%ld, outbuf:%s\n", outlen, outbuf);
memset(inbuf, 0, sizeof(inbuf));
/* Uncompress */
if (uncompress(inbuf, &inlen, outbuf, outlen) != Z_OK){
fprintf(stderr, "Uncompress failed!\n");
return -1;
}
printf("Uncompress Success!\n");
printf("\rinlen:%ld, inbuf:%s\n", inlen, inbuf);
/* free memory */
if (outbuf != NULL){
free(outbuf);
outbuf = NULL;
}
return 0;
}
这里infate
和defate
其实是指两组函数
deflateInit() + deflate() + deflateEnd()
用于完成流的压缩inflateInit() + inflate() + inflateEnd()
用于完成解压缩功能z_stream
是上面两组函数中用到的,用来表示流的数据结构。
typedef struct z_stream_s {
z_const Bytef *next_in; /* next input byte */
uInt avail_in; /* number of bytes available at next_in */
uLong total_in; /* total number of input bytes read so far */
Bytef *next_out; /* next output byte should be put there */
uInt avail_out; /* remaining free space at next_out */
uLong total_out; /* total number of bytes output so far */
z_const char *msg; /* last error message, NULL if no error */
struct internal_state FAR *state; /* not visible by applications */
alloc_func zalloc; /* used to allocate the internal state */
free_func zfree; /* used to free the internal state */
voidpf opaque; /* private data object passed to zalloc and zfree */
int data_type; /* best guess about the data type: binary or text */
uLong adler; /* adler32 value of the uncompressed data */
uLong reserved; /* reserved for future use */
} z_stream;
看下两组函数的原型:
int deflateInit (z_streamp strm, int level); //初始化压缩状态,关联相关的z_stream数据结构和压缩比例
int deflate (z_streamp strm, int flush); //压缩数据, flush表示以何种方式将压缩的数据写到缓冲区中。
int deflateEnd (z_streamp strm); //压缩结束
int inflateInit (z_streamp strm);
int inflate (z_streamp strm, int flush);
int inflateEnd (z_streamp strm);
关于这两组函数的具体使用, examples目录下有几个具体的例子(如zpipe.c
),可以直接参考。