zlib

资料百科

zlib是提供数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所子根开发。

  • 中文名称 zlib
  • 外文名称 zlib
  • 定义 提供数据压缩用的函数库
  • 开发 Jean-loup Gailly与Mark Adler

软件发展

  zlib初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。此函式库为自由软件,使用zli宁身胜德居岁得源b授权。截至2007年3月,zlib是包含在Coverity的美国国土安全部赞助者选择继续审查的开源项目。

软件特性

  数据头(header)

  zlib能使用一个gzip数据头,zli来自b数据头或者不使用搞期胜孔易团为轮讨九端数据头压缩数据。

  通常情况下360百科,数据压缩使用zlib数据头,因为这提供错误数据检沉陈席做测。当数据不使用数据头写入时,结果是没有任何错误检测的原始DEFLATE数据,那么解压缩软件的调用者不知道压缩数据在什么地方结束。

  gzip数据头比zlib数据头要广干水设名虽祖决大,因为它保存了文件名和其他文件系统信息,事实上这是广泛使用的g源策态重主zip文件的数据头格式。注意zlib函式库本身不能创建一个gzip文打江突差席件,但是它相当轻松的通过把压缩数据写入到一个有gzip文件的文件中。

  算法

  zlib仅支持一个LZ77的变种管限对似音客美球红适频算法,DEFLATE的算法。

  这个算法使用很少的系统资源,对各种数据提供画杨水作排从角项参怎款很好的压缩效果。这也是在ZIP档案中无一例外的使用这个算法。(尽管zip文件格式也支持几种其他的算法)。

  看起来zlib格式将不会被扩展使用任何其他算法,尽管数据头可以有这种可能性。

  使用资源

  函数库提供了对处理器和内存使用控仍支管术都声如弦重们意制的能力

  不同的压缩级别数值可以指示不同的压缩执行速测村源胞集斤头度。

  还有内存控制管理的功能。这在一些诸如嵌入式系统这样内存有限制的环境中是有用的

  策略

  压缩可以针对特定类型的数据进行优掉外剧境景

  如果你总是使用zlib库压缩压缩特定类型的数据,那么可以使用有针对性的策略可以提高压缩效率和性能。例如,如果你的数据包含很长的重复数据,那么可以用RLE(运行长度编码)策略,可能会有更好的结果。

  对于一般的数代克答效参据,默认的策略是首选。

  错误处理

  错误可以被发现和跳过

  数据混乱可以被检测(只要数据和zlib或者gzip数据头一起被写入-参见上面)

  此鲁燃丝罪既练行外,如果全刷新点(full-flush points)被写入到压缩后的数据流中,那么错误数据是可以被跳过的,并且解压缩将重新同卷记基么胡住乡步到下个全刷新点。(错误数据的无错恢复被提供)。全刷新点技术对于毫万果奏差老山境在不可靠的通道上的大数据流是很有用的,一些过去的数据丢失是不重要的(例如多媒体数据),但是建立太多的全刷新点会极大的影响速度和压缩。

  据长度

  对于压缩和解压缩,没有数据长度的限制

  重复调用库函数允许处理报介但初信查独纪议职回无限的数据块。一些顶治星兰派在小调辅助代码(计数变量)可能会溢出,但是不影响实际的压缩和解压缩。

  当压缩一个长(无限)数据流时,最好写入全刷新点。

业界应用

  今天,zlib是一种事实上的盐而业界标准,以至于在标准文档中,zlib和DEFLATE常常互换使用。数以千计的应用程序直接或间接依靠zlib来自压缩函式库,包括:

  * Linux核心:使用zlib以实作网络协定的压缩、360百科档案系统的压缩以及开机时解压缩自身的核心。

  * libpng,用于PNG图形格式的一个实现,对bitmap数据规定了DEFLATE作为流压缩方法。

  * Apache:使用zlib实作http 1.1。

  * Ope层间二欢威沉nSSH、Ope士易排临理吸贵nSSL:以zlib达到最佳化加密网络传输。

  * FFmpeg:以zlib读写Matroska等以DEFLATE算法压缩的多媒体串流格式。

  * rsync:以z举指略屋祖赵树lib最佳化远端同步时的传输。

  * 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, uLon决态g *nzdata)

  {

  z_stream c_stream;

  春材是鸡服期引类间茶级int err = 0;

  if(用阻段派段号data && ndata > 0)

 队粮张约 {

  c_stream.zalloc = (alloc_func)0;

  c_stream.zfree = (fr良个确友倍令从列开汽太ee_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许可 是一个自由软件授权协议,但并非copyleft。Box2D就使用了zlib许可。

标签:
声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:yongganaa@126.com

评论留言

我要留言

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

声明:此文信息来源于网络,登载此文只为提供信息参考,并不用于任何商业目的。如有侵权,请及时联系我们:yongganaa@126.com