1. zlib簡介
zlib 適用於數據壓縮的函式庫,由Jean-loup Gailly (負責compression)和 Mark Adler (負責decompression)開發。
zlib被設計成一個免費的、通用的、法律上不受阻礙(即沒有被任何專利覆蓋) 的無損數據壓縮庫。zlib幾乎適用於任何計算器硬件和操作系統。
zlib本身的數據格式可以進行跨平臺的移植。 與在Unix上適用的LZW壓縮方法 以及 GIF 圖像壓縮不同, zlib中適用的壓縮方法從不對數據進行拓展。(LZW在極端情況下會導致文件大小變爲原來的兩倍、甚至三倍)。zlib的內存佔用也是獨立於輸入數據的,並且在必要的情況下可以適當減少部分內存佔用。
2. 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
3. zlib的使用
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 <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <zlib.h>
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;
}
3.2 infate、deflate、z_stream介紹
這裏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
),可以直接參考。