标题：zlib
特性
数据头(header)zlib能使用一个gzip数据头，zlib数据头或者不使用数据头压缩数据。
通常情况下，数据压缩使用zlib数据头，因为这提供错误数据检测。当数据不使用数据头写入时，结果是没有任何错误检测的原始DEFLATE数据，那么解压缩软件的调用者不知道压缩数据在什么地方结束。
gzip数据头比zlib数据头要大，因为它保存了文件名和其他文件系统信息，事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件，但是它相当轻松的通过把压缩数据写入到一个有gzip文件头的文件中。算法目前zlib仅支持一个LZ77的变种算法，DEFLATE的算法。
这个算法使用很少的系统资源，对各种数据提供很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。（尽管zip文件格式也支持几种其他的算法）。
看起来zlib格式将不会被扩展使用任何其他算法，尽管数据头可以有这种可能性。使用资源函数库提供了对处理器和内存使用控制的能力
不同的压缩级别数值可以指示不同的压缩执行速度。
还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的。策略压缩可以针对特定类型的数据进行优化
如果你总是使用zlib库压缩压缩特定类型的数据，那么可以使用有针对性的策略可以提高压缩效率和性能。例如，如果你的数据包含很长的重复数据，那么可以用RLE（运行长度编码）策略，可能会有更好的结果。
对于一般的数据，默认的策略是首选。错误处理错误可以被发现和跳过
数据混乱可以被检测（只要数据和zlib或者gzip数据头一起被写入－参见上面）
此外，如果全刷新点（full-flush points）被写入到压缩后的数据流中，那么错误数据是可以被跳过的，并且解压缩将重新同步到下个全刷新点。（错误数据的无错恢复被提供）。全刷新点技术对于在不可靠的通道上的大数据流是很有用的，一些过去的数据丢失是不重要的（例如多媒体数据），但是建立太多的全刷新点会极大的影响速度和压缩。数据长度对于压缩和解压缩，没有数据长度的限制
重复调用库函数允许处理无限的数据块。一些辅助代码（计数变量）可能会溢出，但是不影响实际的压缩和解压缩。
当压缩一个长（无限）数据流时，最好写入全刷新点。
业界应用
今天，zlib是一种事实上的业界标准，以至于在标准文档中，zlib和DEFLATE常常互换使用。数以千计的应用程序直接或间接依靠zlib压缩函式库，包括：
* Linux核心：使用zlib以实作网络协定的压缩、档案系统的压缩以及开机时解压缩自身的核心。
* libpng，用于PNG图形格式的一个实现，对bitmap数据规定了DEFLATE作为流压缩方法。
* Apache：使用zlib实作http 1.1。
* OpenSSH、OpenSSL：以zlib达到最佳化加密网络传输。
* FFmpeg：以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。
* rsync：以zlib最佳化远端同步时的传输。
* The dpkg and RPM package managers, which use zlib to unpack files from compressed software packages.
* Subversion 、Git和 CVS 版本控制 系统，使用zlib来压缩和远端仓库的通讯流量。
* dpkg和RPM等包管理软件：以zlib解压缩RPM或者其他封包。
因为其代码的可移植性，宽松的许可以及较小的内存占用，zlib在许多嵌入式设备中也有应用。
使用范例
以下代码可直接用于解压HTTP gzip
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <zlib.h>
/* Compress data */
int zcompress(Bytef *data, uLong ndata, 
Bytef *zdata, uLong *nzdata)
{
z_stream c_stream;
int err = 0; 
if(data && ndata > 0)
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
if(deflateInit(&c_stream, Z_DEFAULT_COMPRESSION) != Z_OK) return -1;
c_stream.next_in = data;
c_stream.avail_in = ndata;
c_stream.next_out = zdata;
c_stream.avail_out = *nzdata;
while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) 
{
if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;
}
if(c_stream.avail_in != 0) return c_stream.avail_in;
for (;;) {
if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;
if(err != Z_OK) return -1;
}
if(deflateEnd(&c_stream) != Z_OK) return -1;
*nzdata = c_stream.total_out;
return 0;
}
return -1;
}
/* Compress gzip data */
int gzcompress(Bytef *data, uLong ndata, 
Bytef *zdata, uLong *nzdata)
{
z_stream c_stream;
int err = 0;
if(data && ndata > 0)
{
c_stream.zalloc = (alloc_func)0;
c_stream.zfree = (free_func)0;
c_stream.opaque = (voidpf)0;
if(deflateInit2(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 
-MAX_WBITS, 8, Z_DEFAULT_STRATEGY) != Z_OK) return -1;
c_stream.next_in = data;
c_stream.avail_in = ndata;
c_stream.next_out = zdata;
c_stream.avail_out = *nzdata;
while (c_stream.avail_in != 0 && c_stream.total_out < *nzdata) 
{
if(deflate(&c_stream, Z_NO_FLUSH) != Z_OK) return -1;
}
if(c_stream.avail_in != 0) return c_stream.avail_in;
for (;;) {
if((err = deflate(&c_stream, Z_FINISH)) == Z_STREAM_END) break;
if(err != Z_OK) return -1;
}
if(deflateEnd(&c_stream) != Z_OK) return -1;
*nzdata = c_stream.total_out;
return 0;
}
return -1;
}
/* Uncompress data */
int zdecompress(Byte *zdata, uLong nzdata, 
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream; /* decompression stream */
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit(&d_stream) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK) return -1;
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
/* HTTP gzip decompress */
int httpgzdecompress(Byte *zdata, uLong nzdata, 
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream = {0}; /* decompression stream */
static char dummy_head[2] = 
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK )
{
if(err == Z_DATA_ERROR)
{
d_stream.next_in = (Bytef*) dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 
{
return -1;
}
}
else return -1;
}
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
/* Uncompress gzip data */
int gzdecompress(Byte *zdata, uLong nzdata, 
Byte *data, uLong *ndata)
{
int err = 0;
z_stream d_stream = {0}; /* decompression stream */
static char dummy_head[2] = 
{
0x8 + 0x7 * 0x10,
(((0x8 + 0x7 * 0x10) * 0x100 + 30) / 31 * 31) & 0xFF,
};
d_stream.zalloc = (alloc_func)0;
d_stream.zfree = (free_func)0;
d_stream.opaque = (voidpf)0;
d_stream.next_in = zdata;
d_stream.avail_in = 0;
d_stream.next_out = data;
if(inflateInit2(&d_stream, -MAX_WBITS) != Z_OK) return -1;
//if(inflateInit2(&d_stream, 47) != Z_OK) return -1;
while (d_stream.total_out < *ndata && d_stream.total_in < nzdata) {
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
if((err = inflate(&d_stream, Z_NO_FLUSH)) == Z_STREAM_END) break;
if(err != Z_OK )
{
if(err == Z_DATA_ERROR)
{
d_stream.next_in = (Bytef*) dummy_head;
d_stream.avail_in = sizeof(dummy_head);
if((err = inflate(&d_stream, Z_NO_FLUSH)) != Z_OK) 
{
return -1;
}
}
else return -1;
}
}
if(inflateEnd(&d_stream) != Z_OK) return -1;
*ndata = d_stream.total_out;
return 0;
}
#ifdef _DEBUG_ZSTREAM
#define BUF_SIZE 65535
int main()
{
char *data = "kjdalkfjdflkjdlkfjdklfjdlkfjlkdjflkdjflddajfkdjfkdfaskf;ldsfk;ldakf;ldskfl;dskf;ld"; 
uLong ndata = strlen(data); 
Bytef zdata[BUF_SIZE];
uLong nzdata = BUF_SIZE;
Bytef odata[BUF_SIZE];
uLong nodata = BUF_SIZE;
memset(zdata, 0, BUF_SIZE);
//if(zcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)
if(gzcompress((Bytef *)data, ndata, zdata, &nzdata) == 0)
{
fprintf(stdout, "nzdata:%d %s\n", nzdata, zdata);
memset(odata, 0, BUF_SIZE);
//if(zdecompress(zdata, ndata, odata, &nodata) == 0)
if(gzdecompress(zdata, ndata, odata, &nodata) == 0)
{
fprintf(stdout, "%d %s\n", nodata, odata);
}
}
}
#endif
zlib许可
[1]zlib许可[2]是一个自由软件授权协议，但并非copyleft。Box2D就使用了zlib许可。
、