-
zlib
编辑
zlib是提供
数据压缩用的函式库,由Jean-loup Gailly与Mark Adler所开发,初版0.9版在1995年5月1日发表。zlib使用DEFLATE算法,最初是为libpng函式库所写的,后来普遍为许多软件所使用。此函式库为自由软件,使用zlib授权。截至2007年3月,zlib是包含在Coverity的
美国国土安全部赞助者选择继续审查的开源项目。
- 中文名
- zlib
- 外文名
- zlib
- 定 义
- 提供数据压缩用的函数库
- 开 发
- Jean-loup Gailly与Mark Adler
数据头(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] 是一个自由软件授权协议,但并非
copyleft。Box2D就使用了zlib许可。
- 参考资料
-
- 利用zlib库进行zip解压
1:到zlib官网上下载zlib,本文下载的是1.2.8的版本. 2:进行./configure,然后make. 3:进入zlib库中的contrib/minizip/路径下make,生成的miniz ...
- 【转】 C++使用zlib库(-)
来自: http://blog.chinaunix.net/uid-24607609-id-2118143.html 今天看到一个gzopen函数,搜了一下他的系列函数,及相关用法 C++使 ...
- Windows下zlib库和libPng库的编译和使用
关于zlib库和libpng是干嘛的,我就不说了,度娘和谷歌都能告诉你.这里主要记录下windows下如何利用vs2010编译和使用这两个库. 一.zlib库的编译 首先要下载这个库,这个谷歌和百度也 ...
- 如何在 window7 环境编译 zlib 库?
1.下载最新版本 zlib 库 `下载地址:http://www.zlib.net/ 2.打开vc14项目 解压下载的 zlib.zip 压缩包并打开zlib1211\zlib-1.2.11\cont ...
- [Zlib]_[初级]_[使用zlib库压缩和解压STL string]
场景 1.一般在使用文本json传输数据, 数据量特别大时,传输的过程就特别耗时, 因为带宽或者socket的缓存是有限制的, 数据量越大, 传输时间就越长. 网站一般使用gzip来压缩成二进制. 说 ...
- VS编译 x64版本zlib库
编译的过程倒也不是很难.我把编译的源码和脚本及说明都放在gitee上了. 详细的可以见这里 https://gitee.com/solym/zlib-1.2.11.git 可以参考这些文章 win10 ...
- Zlib库的安装与使用
在实际应用中经常会遇到要压缩数据的问题,常见的压缩格式有zip和rar,而Linux下那就更多了,bz2,gz,xz什么的都有,单单Linux下的解压和压缩命令就有好多呢?没有什么好不好的.查了资料, ...
- zlib库的编译及使用
* 打开网址http://zlib.net/ 下载zlib源码, * 解压压缩包,进入目录:C:\Users\Administrator\Desktop\zlib-1.2.11\zlib-1.2.11 ...
- zlib库剖析(1):实现概览
zlib库剖析(1):实现概览 http://blog.csdn.net/zhoudaxia/article/details/8034606 http://blog.chinaunix.net/uid ...
随机推荐
- 修改TrustedInstaller权限文件(无法删除文件)
1. 右击需要修改的文件-属性 2. 切换到"安全"选项卡,点击"高级"按钮. 3. 切换到"所有者"选项卡 一般情况下默 ...
- LeetCode 笔记24 Palindrome Partitioning II (智商碾压)
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- 信息安全系统设计基础实验一 20135210&20135218
北京电子科技学院(BESTI) 实 验 报 告 课程: 密码系统设计基础 ...
- gdb调试汇编堆栈分析
代码(src/05/gdb.c) int g(int x) { return x + 4; } int f(int x) { return g(x); } int main(void) { retur ...
- UITableView和UICollectionView的Cell高度的几种设置方式
UITableViewCell 1.UITableView的Cell高度默认由rowHeight属性指定一个低优先级的隐式约束 2.XIB中可向UITableViewCell的contentView添 ...
- 面试官的七种武器:Java篇
起源 自己经历过的面试也不少了,互联网的.外企的,都有.总结一下这些面试的经验,发现面试官问的问题其实不外乎几个大类,玩不出太多新鲜玩意的.细细想来,面试官拥有以下七种武器.恰似古龙先生笔下的武侠世界 ...
- DELL VENUE 11 PRO系统损坏之后的解决办法
首页说明下我的平板是dell venue 11 pro atom版+win8.1版. 前两天测试玩win10,结果后来几天这货直接开不了机了,每次提示自动修复,但是却说找不到某一文件,然后蓝屏,win ...
- C#基础知识系列六(静态类和静态类成员)
静态类 静态类与非静态类基本相同,但存在一个区别:静态类不能实例化. 也就是说,不能使用 new 关键字创建静态类类型的变量. 因为没有实例变量,所以要使用类名本身访问静态类的成员. 例如,如果名为 ...
- EasyUI——实现展示后台数据代码
下面是View显示代码: @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml" ...
- poppin_xpower_ 常城