ZLIB压缩数据格式规范v3.3

原版文档,及官方代码库实现,可以从zlib官网下载获取。

备忘录状态

这个备忘录为互联网社区提供的信息。这个备忘录未指定任何形式的互联网标准。这个备忘录的分发是不受限制的。

IESG注:

IESG 对本文档中包含的任何知识产权声明的有效性不持任何立场。

注意

Copyright 1996 L. Peter Deutsch and Jean-Loup Gailly
允许出于任何目的的免费复制和分发本文档,包括翻译为其他语言,但需要提供版权声明,并且该通知需要保留,对原始文档中任何实际的改变和删除也需明确标记。
可以在ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html获取该文档及相关文档的最新版本。

摘要

该规范定义了无损压缩数据格式。对于任意长度顺序显示的数据流信息,可以仅使用部分存储的前部数据进行数据的产生和使用。该格式目前使用DEFLATE压缩方法,但是可以轻松扩展使用其他压缩方法。它可以以专利未涵盖的方式轻松实现。这个规范还定义了ADLER-32校验和算法(Fletcher校验和算法的扩展和改进),用于检测数据损坏,并且提供了计算算法。

1、介绍

1.1 目的

这个规范的目的是定义一种无损数据压缩格式:

  • 独立于CPU类型,操作系统,文件系统和字符编码,能够被压缩和解压缩转换;
  • 对于任意长度顺序显示的数据流信息,可以仅使用部分存储的前部数据进行数据的产生和使用,因此可以在数据通信或类似结构中使用,如Unix过滤器;
  • 能够使用多种不同的压缩算法;
  • 可以以专利位涵盖的方式轻松实现,因此可以自由实践。
    该规范定义的数据格式,不允许试图随机访问压缩数据。
1.2 目标受众

该规范旨在供软件的实现者用来将数据压缩为zlib格式及从zlib格式解压缩数据。该规范的内容假定在位和其他原始级别的数据编程方面具有基本的背景知识。

1.3 范围

该规范指定了可用于任意字节的序列内内存压缩的压缩数据格式。

1.4 遵守

除非以下另有说明,否则兼容的解压缩器必须能够接受和解压缩符合此处介绍的所有规格的设置任何数据;一个符合标准的压缩机也必须能够产生符合此处介绍的所有规格数据集。

1.5 所用术语和惯例定义

byte:以8bit为单位进行存储或传输的单元(与八位字节相同)。(对于本规范,一个byte确切的8bit,即使是在字符存储位数不是8的机器上)。byte中bit的位置请参见下文。

1.6 相对旧版本的修改

3.1版本是该规范的第一个公开发行版本。在3.2版中,一些术语被修改,并且为了更清晰,对Adler-32的示例代码进行了重写。在3.3版中,引入了预设字典,并且将规范转换为RFC格式。

2、详细规范

2.1、总体惯例

在下图中,这样的框:
在这里插入图片描述
表示一个byte;这样的框:
在这里插入图片描述
代表可变数目的字节。
byte存储在计算机中没有“bit顺序”,因此他们总是被视为一个单位。 然而,被视为0到255之间的整数的字节确实具有最高和最低有效位,并且由于我们写数字时在左边写最高有效数字,写字节时在左边写最高有效bit。在下图中,我们对byte中的bit进行编号,以便bit0是最低有效位,即位编号:
在这里插入图片描述
在计算机中,一个数可能由多个字节组成。 所描述格式的所有多字节数字
此处首先以MOST有效字节存储(在较低的存储器地址处)。例如,十进制数据520存储为:
在这里插入图片描述

2.2 数据格式

一个zlib流有以下结构:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
ADLER32之后的可能出现的所有数据都不属于zlib流。

CMF(Compression Method and flags)
  • 这个字节根据压缩方法的不同被分为4bit压缩方法和4bit信息字段。
    • bits 0 to 3 CM Compression method,压缩方法
    • bits 4 to 7 CINFO Compression info,压缩信息
CM(Compression method)
  • 这个标识了文件中使用的压缩方法。CM = 8表示窗口大小最大为32K的“deflate”压缩方法。这个方法也被gzip和PNG使用(请参见第3章节的参考文献[1]和参考文献[2],及相关的参考文档)。CM = 15被保留。它可能被使用在本规范的未来版本,以指示在压缩之前存在一个额外的字段数据。
CINFO(Compression info)
  • 对于CM = 8,CINFO是LZ77窗口大小以2为低的对数,减去8(CINFO = 7表示窗口大小为32K),在这个版本规范中,不允许CINFO的值大于7。在该规范中对于不等于8的CM,未定义CINFO。
FLG(FlsGs)
  • 该标志字节划分如下:
    • bits 0 to 4 FCHECK Check bit for CMF and FLG,检查CMF和FLG标志位
    • bits 5 FDICT Preset dictionary, 预设字典
    • bits 6 to 7 FLEVEL Compression level,压缩等级
  • 当将FCHECK值视为存储的16位无符号整数时,其值必须使得CMF和FLG以MSB顺序(CMF * 256 + FLG)存储,是31的整数倍。
FDICT(Preset dictionary)
  • 如果设置了FDICT位,则在FLG字节后将存在DICT词典标识符。这个词典是一个最初被馈送到压缩器而不产生任何压缩输出的字节序列。DICT是此字节序列的Adler-32校验和(请参阅下文的ADLER32的定义)。解压缩器能够使用此标识符来确定已使用了哪个字典用于压缩。
FLEVEL(Compression level)
  • 这个标识能够被使用于特殊的压缩方法。这个“deflate”方法(CM = 8)标志设置如下:
    • 0 - 使用最快的压缩算法
    • 1 - 使用快的压缩算法
    • 2 - 使用默认的压缩算法
    • 3 - 使用最大的压缩,最慢的算法
  • 解压缩不需要FLEVEL中的信息;它可能用于指示是否重新压缩。
Compress Data
  • 对于压缩方法8,这个压缩数据按L.Peter的文档“DEFLATE压缩数据格式规范”以deflate压缩数据格式存储。(请参见下文第3章中的参考文献[3])
  • 在该版本的zlib规范中未指定其他压缩数据格式。
ADLER32(Adler-32 checksum)
  • 这是根据Adler-32算法计算出的未压缩数据(不包含任何字典数据)的校验和值。这个算法是ITU-T X.224 / ISO8073标准中使用的算法Fletcher的32位扩展和改进。(请参见下文第三章中的参考文献[4]和参考文献[5])。
  • Adler-32是由每个字节累加的两个和组成:s1是所有字节的累加和,s2是所有s1值得累加和。这两个和都对65521做取模运算。s1初始化为1,s2初始化为0。Adler-32校验和以最高有效字节在前(网络)得顺序存储为s2 * 65536 + s1。
2.3 遵守

符合标准得压缩器必须能够产生具有正确得CMF,FLG和ADLER32的流,但无需支持预设字典。当zlib数据格式作为另一种标准数据格式的一部分时,压缩器只能使用此其他数据格式指定的预设字典。如果其他格式不适用预设字段功能,压缩器不能设置FDICT标志。
符合标准的解压缩器必须检查CMF,FLG和ADLER32,并且如果有不正确的值需要提供错误提示。如果CM并不是规范中定义的值(在此版本中仅允许值为8),符合标准的解压缩器必须给一个错误提示,因为其他的值可能表明存在新的功能,这将可能会导致错误地解释后续数据。如果设置了FDICT但DICTID并没有已知的预设字段,符合标准的解压缩器必须给出错误提示。解压缩器可能会忽略FLEVEL并仍然符合要求。当zlib数据格式被用作另一种标准格式的一部分,符合标准的解压缩器必须hi吃所有其他格式指定的预设字典。当其他格式不使用预设字典功能时,符合标准的解压缩器必须拒绝设置;额FDICT标志的任何流。

3、引用

[1] Deutsch, L.P.,“GZIP Compressed Data Format Specification”, available in ftp://ftp.uu.net/pub/archiving/zip/doc/
[2] Thomas Boutell, “PNG (PortableNetworkGraphics) specification”, available in ftp://ftp.uu.net/graphics/png/documents/
[3] Deutsch, L.P.,“DEFLATE Compressed Data Format Specification”, available in ftp://ftp.uu.net/pub/archiving/zip/doc/
[4] Fletcher, J. G., “An Arithmetic Checksum for Serial Transmissions,” IEEE Transactions on Communications, Vol. COM-30, No. 1, January 1982, pp. 247-252.
[5] ITU-T Recommendation X.224, Annex D, “Checksum Algorithms,” November, 1993, pp. 144, 145. (Available from gopher://info.itu.ch). ITU-T X.244 is also the same as ISO 8073.

4、源码

可以从ftp://ftp.uu.net/pub/archiving/zip/zlib/获得有关“ zlib”兼容库的C语言实现的源代码。

5、安全注意事项

无法检查ADLER32校验和值的解码器可能会遭受未检测到的数据损坏。

6、致谢

本文档中引用的商标是其各自所有者的财产。
Jean-Loup Gailly和Mark Adler设计了zlib格式并编写了本文档中描述的相关软件规格。 Glenn Randers-Pehrson将此文档转换为RFC和HTML格式。

7、作者地址

L. Peter Deutsch

  • Aladdin Enterprises
  • 203 Santa Margarita Ave.
  • Menlo Park, CA 94025
  • Phone: (415) 322-0103 (AM only)
  • FAX: (415) 322-1734
  • EMail: ghost@aladdin.com

Jean-Loup Gailly

Questions about the technical content of this specification can be sent by email to

Editorial comments on this specification can be sent by email to

8、附录:基本原理

8.1、预设字典

预设字典对于压缩短输入序列特别有用。压缩器可以利用字典上下文对输入进行更加紧凑的方式进行输入编码。解压缩器能够使用通过解压缩字典的压缩版本适当上下文初始化而没有任何数据输出。但是对于某些压缩算法,如deflate算法,这个操作无需实际执行任何的解压缩即可实现。
压缩器和解压缩必须使用完全相同的字典。字典可能是固定的或者可能根据输入数据的种类从一定数量的预定义字典中选择。解压缩器可以通过检查字典来确认压缩器选泽了哪个字典标识。本文档并未指定预定义词典的内容,因为最佳字典是特定于应用程序的。使用zlib规范的此功能的标准数据格式必须明确定义允许的字典。

8.2、Adler-32算法

Adler-32算法比CRC32算法快得多,但未检测到错误的概率还是极低的。
无符号长累加器的模可以延迟552字节,因此模运算的时间是微不足道的。如果字节是a,b,c,则第二个和为3a + 2b + c + 3,因此位置和顺序敏感,不像第一个和仅仅是个校验和。这个65521也是主要的重要的对于避免可能的大量两个字节错误而校验不变的情况。(Fletcher校验和使用255,这不是素数,这也使得Fletcher检查对单字节更改不敏感0 <->255。)
将累加和s1初始化未1而不是0,使得序列的长度成为s2的一部分,因此长度不许单独检查。(任何零序列的Fletchar的校验和为0)。

9、附录:示例代码

下面的代码计算数据缓冲区的ADLER-32校验和。它是为了清晰而写的,不是为了速度。
示例代码是用ANSI C编程语言编写的。非C用户可能会发现使用这些工具更容易阅读提示:

  • &, Bitwise AND operator.
  • >>, Bitwise right shift operator. When applied to an unsigned quantity, as here, right shift inserts zero bit(s) at the left.
  • <<, Bitwise left shift operator. Left shift inserts zero bit(s) at the right.
  • ++, “n++” increments the variable n.
  • %, modulo operator: a % b is the remainder of a divided by b.
#define BASE 65521 /* largest prime smaller than 65536 */
/* Update a running Adler-32 checksum with the bytes buf[0..len-1] 
and return the updated checksum. The Adler-32 checksum should be 
initialized to 1.

Usage example:
	unsigned long adler = 1L;
	while (read buffer(buffer, length) != EOF)  {
		adler = update adler32(adler, buffer, length);
	}
	if (adler != original adler) error();
*/

unsigned long update adler32(unsigned long adler, unsigned char *buf, int len)
{
	unsigned long s1 = adler & 0xffff;
	unsigned long s2 = (adler >> 16) & 0xffff;
	int n;
	
	for (n = 0; n < len; n++) {
		s1 = (s1 + buf[n]) % BASE;
		s2 = (s2 + s1) % BASE;
	}
	return (s2 << 16) + s1;
}

/* Return the adler32 of the bytes buf[0..len-1] */
unsigned long adler32(unsigned char *buf, int len)
{
	return update adler32(1L, buf, len);
}
  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值