zlib软件包包含zlib库,很多程序中的压缩或者解压缩函数都会用到这个库。zlib适用于数据压缩的函式库,几乎适用于任何计算器硬件和操作系统。
特性:数据头(header)zlib能使用一个gzip数据头、zlib数据头或者不使用数据头压缩数据。
通常情况下,数据压缩使用zlib数据头,因为这提供错误数据检测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者不知道压缩数据在什么地方结束。
gzip数据头比zlib数据头要大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的gzip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文件,但是它相当轻松的通过把压缩数据写入到一个有gzip 文件头的文件中。
算法
zlib仅支持一个LZ77的变种算法,DEFLATE的算法。
这个算法使用很少的系统资源,对各种数据提供很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。(尽管zip文件格式也支持几种其他的算法)。
看起来zlib格式将不会被扩展使用任何其他算法,尽管数据头可以有这种可能性。
使用资源
函数库提供了对处理器和内存使用控制的能力
不同的压缩级别数值可以指示不同的压缩执行速度。
还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的。
策略
压缩可以针对特定类型的数据进行优化
如果你总是使用zlib库压缩压缩特定类型的数据,那么可以使用有针对性的策略可以提高压缩效率和性能。例如,如果你的数据包含很长的重复数据,那么可以用RLE(运行长度编码)策略,可能会有更好的结果。
对于一般的数据,默认的策略是首选。
错误处理
错误可以被发现和跳过
数据混乱可以被检测(只要数据和zlib或者gzip数据头一起被写入-参见上面)
此外,如果全刷新点(full-flushpoints)被写入到压缩后的数据流中,那么错误数据是可以被跳过的,并且解压缩将重新同步到下个全刷新点。(错误数据的无错恢复被提供)。全刷新点技术对于在不可靠的通道上的大数据流是很有用的,一些过去的数据丢失是不重要的(例如多媒体数据),但是建立太多的全刷新点会极大的影响速度和压缩。
数据长度
对于压缩和解压缩,没有数据长度的限制
重复调用库函数允许处理无限的数据块。一些辅助代码(计数变量)可能会溢出,但是不影响实际的压缩和解压缩。
当压缩一个长(无限)数据流时,最好写入全刷新点。
使用范例
以下代码可直接用于解压HTTPgzip
#include<stdlib.h>#include<string.h>#include<errno.h>#include<zlib.h>/*Compressdata*/intzcompress(Bytef*data,uLongndata,Bytef*zdata,uLong*nzdata){z_streamc_stream;interr=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)returnc_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;return0;}return-1;}/*Compressgzipdata*/intgzcompress(Bytef*data,uLongndata,Bytef*zdata,uLong*nzdata){z_streamc_stream;interr=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)returnc_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;return0;}return-1;}/*Uncompressdata*/intzdecompress(Byte*zdata,uLongnzdata,Byte*data,uLong*ndata){interr=0;z_streamd_stream;/*decompressionstream*/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;/*forcesmallbuffers*/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;return0;}/*HTTPgzipdecompress*/inthttpgzdecompress(Byte*zdata,uLongnzdata,Byte*data,uLong*ndata){interr=0;z_streamd_stream={0};/*decompressionstream*/staticchardummy_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;/*forcesmallbuffers*/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;}}elsereturn-1;}}if(inflateEnd(&d_stream)!=Z_OK)return-1;*ndata=d_stream.total_out;return0;}/*Uncompressgzipdata*/intgzdecompress(Byte*zdata,uLongnzdata,Byte*data,uLong*ndata){interr=0;z_streamd_stream={0};/*decompressionstream*/staticchardummy_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;/*forcesmallbuffers*/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;}}elsereturn-1;}}if(inflateEnd(&d_stream)!=Z_OK)return-1;*ndata=d_stream.total_out;return0;}#ifdef_DEBUG_ZSTREAM#defineBUF_SIZE65535intmain(){char*data="kjdalkfjdflkjdlkfjdklfjdlkfjlkdjflkdjflddajfkdjfkdfaskf;ldsfk;ldakf;ldskfl;dskf;ld";uLongndata=strlen(data);Bytefzdata[BUF_SIZE];uLongnzdata=BUF_SIZE;Bytefodata[BUF_SIZE];uLongnodata=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
评论