Deflate数据格式分析(RFC-1951)

zlib deflate gzip区别 适用于单个文件,也使用压缩压缩方法。提供了压缩和解压缩代码,供 zip、gzip、)和许多其他应用程序使用。 阅读详情
AI摘要

本文深入解析Delate压缩格式,介绍其独特的数据块结构、霍夫曼编码应用及LZ77算法结合,阐述如何实现高效数据压缩。文章涵盖编码细节、压缩数据表示、霍夫曼树生成与解码流程。

Delate压缩格式

综述

被压缩的数据是许多块组成的集合,每个块的大小是任意的,但是要小于65535字节。

每个块都有两个部分:

  • 一对霍夫曼编码树,霍夫曼树本身利用霍夫曼编码进行压缩。
  • 被压缩的数据。

其中霍夫曼树使用长度数组生成。长度数组本身也用霍夫曼编码进行存储。

被压缩的数据包括两种类型的元素:

  • literal bytes,在前32k中没有相匹配的字符串,即无法从前32k中复制出来的字符串。
  • pointers,是一个数据对,形式为<length,backward distance>。限制backward distance的大小小于32K字节,length小于258字节,当并不限制被压缩块的大小。

每种类型的元素(literals, distance, lengths)在数据中都是以霍夫曼编码的形式出现的,用一颗树对literals和length进行编码,用另一颗树对距离进行编码。对每一块进行编码的树 用一个固定的组成形式出现在该块的压缩数据之前。

编码细节

编码中的数据是不定长的位序列,而不是字节。所以没有必要关心究竟是大端存储还是小端存储。

下面是如何将位序列打包成比特流的规则:

  • 数据元素按照字节序号的增加来进行排列的。即先填充这个字节的最低有效位。
  • 除了霍夫曼编码的数据元素外,都是以数据的最低有效位开始存储。
  • 霍夫曼编码从最好有效位开始存储。

也就是说,数据进行处理的时候,如果不是霍夫曼编码,那么先读到的数据就是这个数据的最低位,如果是霍夫曼编码,读到的就是这个数据的最高位。

数据就按照字节顺序,从字节最低位开始读即可。

经过LZ77压缩后的数据的表示

再经过LZ77算法压缩之后的数据通过两个alphabet进行表示。

  • literal/length alphabet,包含了符号和长度
  • distance alphabet,表示向前的的偏移量

这里符号指字典中的元素,编码指某个元素的二进制编码。

literal/length alphabet

该表含义如下:

  • 0-255:literal bytes,相当于符号本身,解码时直接复制到输出流中就可以了。
  • 256:块的结束标志。表示压缩数据块的结束
  • 257-285:需要复制的长度。在每个长度之后可能会跟着一部分额外的bit,真实的数值为这几个bit的数值加上base。

具体的表格如下:

CodeLength baseExtra bits
25730
25840
25950
26060
26170
26280
26390
264100
265111
266131
267151
268171
269192
270232
271272
272312
273353
274433
275513
276593
277674
278834
279994
2801154
2811315
2821635
2831955
2842275
2852580
distance alphabet

distance的解码规则与上一个表相同。

CodeLength baseExtra bits
010
120
230
340
451
571
692
7132
8173
9253
10334
11494
12655
13975
141296
151936
162577
173857
185138
197698
2010259
2115379
22204910
23307310
24409711
25614511
26819312
271228912
281638513
292457713

Deflate格式中的霍夫曼编码

在Deflate格式中,每个字母表使用的霍夫曼编码都有两个额外的规则:

  • 每个长度对应的编码的取值必须是连续的,并且与他们代表的符号出现顺序相同。
  • 较短的编码在索引时要先于较长的码。

虽然LZ算法已经减少了数据量,但可以用霍夫曼编码进行进一步的压缩。

Deflate格式中最长的编码长度为15。最短的长度为1,0是保留字,用来表示这个符号根本就没有在压缩数据中出现。

长度数组(Code length alphabet)

Deflate格式并不存储霍夫曼编码本身,而是存储编码的长度数组,并通过特定的算法反解出霍夫曼编码。具体解法如下:

假设一共有13个符号,字面值为0-12,编码的长度分别为{2, 0, 3, 4, 4, 0, 2, 4, 4, 0, 4, 5, 5},可以看到1,5,9根本就没有出现过。

  • 统计每个编码长度出现的频数,{0, 0, 2, 1, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},比如2出现了两次,对应位置就是2,如上文所说,0表示这个编码没有出现过,在频数数组里,0出现的次数时钟为0.
  • 决定初始编码的值。具体算法会在代码中给出。
  • 最后输出实际的编码表
#include <iostream>
#include <fstream>
#include <algorithm>
using namespace std;
const int sym_num = 13;
unsigned int code_length[sym_num] = {2, 0, 3, 4, 4, 0, 2, 4, 4, 0, 4, 5, 5},real_code[sym_num];
void GetCode()
{
    unsigned int code_num[16] = {0}, code[16] = {0};
    for( auto i : code_length ) code_num[i] ++;
    code_num[0] = 0;
    for( int i = 1; i < 16; ++ i )
        code[i] = (code[i-1] + code_num[i-1]) << 1;
    for( int i = 0; i < sym_num; ++ i )
        if( code_length[i] ) real_code[i] = code[code_length[i]] ++;
}
int main()
{
    GetCode();
}

最终编码结果如下:

0 -> 00
1 -> null
2 -> 001
3 -> 0101
4 -> 1101
5 -> null
6 -> 10
7 -> 0011
8 -> 1011
9 -> null
10 -> 0111
11 -> 01111
12 -> 11111

这一部分数据是高位在左,比如存储1011,那么就按照1,0,1,1的顺序存储。

假如有一段序列:10101010101011111000101000010110111101010

利用字典树进行匹配:1010 1010 11111 00 01 01 00 00 1011 01 1110 1010

然后反解出来:3, 3, 3, 12, 0, 6, 6, 0, 0, 4, 6, 10, 4

对长度数组的编码

由于只需要存储literal/length alphabet和distance alphabet,所以长度数组最长也就315。为了进一步缩短,Deflate中采用了下面这种办法:

  • 0-15为literal编码的长度
  • 16:重复之前的长度x次,读2个额外的比特,假设数值为y,那么x=y+3
  • 17:重复之前的长度x次,读3个额外的比特,假设数值为y,那么x=y+3
  • 18:重复之前的长度x次,读7个额外的比特,假设数值为y,那么x=y+11

块的格式

每一块被压缩的数据以3个头比特位开始。

  • 第一个bit表示BFINAL,只有当前块是最后一块的时候才需要设置BFINAL。
  • 接下来两个bit表示BTYPE
    • 00表示没有压缩
    • 01表示用固定的霍夫曼编码压缩
    • 10表示用动态的霍夫曼编码压缩
    • 11表示错误或者保留

这三个比特位不需要在每个字节的开头,因为每一块可以不占用整数字节的长度。

无压缩的块
0 12 34…
LENNLENLEN byte of literal data
被压缩的块

如前文所述,字母表的大小位0-255,length的大小位0-258,编码时literal和length被合并成一个字母表了,大小为0-258。其中0-255表示literal bytes,数值256表示块的结束。257-285代表长度编码,可能额外的位跟在后边。

额外的位应该被声明为整数,并且最高位在最前面。

通过固定霍夫曼码压缩

有规定的表格,按照表格进行解码即可。

Lit ValueBitsCodes
0 - 143800110000 - 10111111
144 - 2559110010000 - 0010111
256 - 27980000000 - 0010111

数值286 - 287不会再压缩的数据中出现,但是参与数据的生成。

距离的编码0 - 31用固定的5bit来表示,可能会像上文一样存在额外的比特。

通过动态霍夫曼码压缩
大小(bit)名称描述
5NLIT-257literal length alphabet中符号的个数
共拥有NLIT的符号。注意这块数据的数值比实际上的数少了257
5NDIST-1distance alphabet中符号的个数,实际值比真实值少1
4NCLEN-4有NCLEN个符号在code length alphabet中,实际值比真实值少4
3*NCLEN在code length alphabet中用来编码前缀码的长度用3bit来表示前缀码表的长度,用这些值可以剪出来code length alphabet所用的霍夫曼树。
表中的下标按如下顺序排列,{16,17,18,0,8,7,9,6,10,15,11,4,12,3,13,2,14,1,15}
如果NCLEN比19小,未涉及的部分填0
可变长在literal/length alphabet和distance alphabet中用来编码前缀码的长度有NLIT+NDIST个元素被编码。先存储literal/length alphabet中前缀码的长度,然后是distance前缀码的长度。
可变长被压缩的数据根据两颗霍夫曼树进行解码。
深入解析RFC 1951:ZLIB压缩算法设计与实现 RFC 1951 定义了DEFLATE压缩算法的精确格式,作为 zlib、gzip、PNG 等广泛使用的技术基础。该标准规定了无损数据压缩的比特级结构,结合 LZ77 与霍夫曼编码,实现高效压缩。RFC 1951《DEFLATE Compressed Data Format Specification version 1.3》是理解该算法权威性的根本依据。该文档由Phil Katz(PKZIP发明者)提出,并由IETF正式发布,明确了DEFLATE压缩数据流的精确结构与解析规则。 阅读详情

相关推荐

二叉树的操作之统计二叉树中节点的个数

一,问题描述 给定一颗二叉树,已知其根结点。 ①计算二叉树所有结点的个数 ②计算二叉树中叶子结点的个数 ③计算二叉树中满节点(度为2)的个数   二,算法分析 找出各个问题的基准条件,然后采用递归的方式实现。 ①计算二叉树所有结点的个数 1)当树为空时,结点个数为0,否则为根节点个数 加上 根的左子树中节点个数 再加上 根的右子树中节点的个数 借助遍历二叉树的思路,每访问一个结...

weixin_34200628的博客 4568

GZIP压缩原理分析(32)——第五章 Deflate算法详解(五23) 动态哈夫曼编码分析(12)构建哈夫曼树(04)

构建literal/length树

jison_r_wang的专栏 4867

MIT 18.03 微分方程 ODE 学习笔记分享——目录

从B站上看到了MIT 微分方程的课程,觉得老爷子讲的真好! 其实微分方程对于工科来说相当重要,但是很多学习也仅把他放在高数里作为单独的一个章节来讲,这是远远不够的。所以对于同学们来说 ,一定要认真听讲,做好笔记! 以下是我的个人学习比较分享。有需要的同学可以做一个参考。 注:个人认为笔记的作用是用来回想起课堂所讲的内容(细节),所以我的笔记风格为以老师讲课思路为准,板书为辅。建议刚开始听这门课的同...

weixin_40664094的博客 2630

RFC1951的部分翻译及原文(1/2) (转)

RFC1951的部分翻译及原文(1/2) (转)[@more@]下面只是rfc文档中的第1,2,3,节,其余部分请参照原文。1. Introduction 1.1. Purpose 本规范是用来定义一个无损的数据压缩格...

cuibeng3549的博客 1050

合金理论自动化工具包(Alloy-Theoretic Automated Toolkit:ATAT)的安装

合金理论自动化工具包(ATAT)是一个通用名称,指的是合金理论工具的集合,它包含了不同的代码工具,具体如下: 1)根据第一性原理(映射和映射)构造集群扩展的代码。簇展开是一种非常紧凑和有效的表达式,给出取代合金的能量作为其构型的函数(即原子的类型位于晶格的哪个位置)。 2)为了计算合金的热力学性质,从聚类展开开始,对晶格模型进行蒙特卡洛模拟(emc2和memc2)的代码。 3)执行晶格动力学计算的代码(fitfc, fitsvsl, svsl) 4)使用简单的物理或半经验模型计算电子和磁自由能贡献

qq_33400046的博客 1万+

基于CNN对抗嵌入的图像隐写——CNN-Based Adversarial Embedding for Image Steganography

CNN-Based Adversarial Embedding for Image Steganography https://ieeexplore.ieee.org/abstract/document/8603808 这篇论文发表在TIFS( IEEE TRANSACTIONS ON INFORMATION FORENSICS AND SECURITY),TIFS是网络与信息安全领域的国际两大顶级期刊之一,中国计算机学会(CCF)推荐的A类期刊,SCI一区TOP期刊,目前影响因子有7多了。 1 概

weixin_48654804的博客 2279

ZIP压缩算法详细分析及解压实例解释(下)

7、ZIP中对CL进行再次压缩的方法 这里仍然沿用Huffman的想法,因为CL也是一堆整数,那么当然可以再次应用Huffman编码。不过在这之前,PK对CL序列进行了一点处理。这个处理也是很精巧的。 CL序列表示一系列整数对应的码字长度,对于literal/length来说,...

962

高能物理相关软件

国内高能物理实验背景     研究物质最深层次结构及相互作用的前沿基础科学。 现代高能物理实验的要素    实例源 、 探测器、   电子学、  触发 DAQ、  原始数据、 刻度、重建 、物理分析、  成果  。 离线软件的地位和作用。    是硬件设备和物理学家的桥梁,是从数据到物理成果转化中的关键和重要的环节。 高能物理实验及其特点 独一无二性,实验规模越来越大,努力省钱(使用

Alan Zhuang的博客 3300

GZIP压缩原理分析(19)——第五章 Deflate算法详解(五10) 算法分析(04) 格式说明(03) 静态哈夫曼编码

静态哈夫曼编码(Compression with fixed Huffman codes),这部分内容只要看格式就好,出现在这里的码表只是为了说明,细节此时可能不懂,但是后面会铺开来讲,不用担心。 静态哈夫曼编码使用一张固定的literal/length码表,码表如下, Lit Value Bits

jison_r_wang的专栏 5211

《备考系统分析师》 - 专栏介绍和目录

本专栏提供软考高级系统分析师全套备考资料,包含四大核心内容:1.详细考点梳理(覆盖基础知识、关键技术、案例实践三大模块16个章节);2.历年真题及解析(2009-2022年所有真题含综合知识、案例分析和论文);3.100+篇高质量论文范文;4.预测模拟题。早鸟价仅需9.9元,可节约80%资料搜集时间,帮助考生高效备考、顺利通过考试。专栏持续更新,有问题可随时联系作者。

数据知道的博客 1万+

如何通过 GitHub Actions 使用 SSH 自动化部署到阿里云 ECS 实例

通过 GitHub Actions 和 SSH 自动化部署,可以显著提高你的开发效率和部署的可靠性。本文介绍了如何生成 SSH 密钥、将公钥添加到阿里云 ECS 实例、将私钥添加到 GitHub Secrets,以及编写 GitHub Actions 工作流来实现自动化部署。希望这篇文章对你有所帮助!

吃面不喝汤的博客 1511

gzip,deflate,zlib辨析

<br />deflate(RFC1951):一种压缩算法,使用LZ77和哈弗曼进行编码;<br />zlib(RFC1950):一种格式,是对deflate进行了简单的封装,他也是一个实现库(delphi中有zlib,zlibex)<br />gzip(RFC1952):一种格式,也是对deflate进行的封装。<br />gzip = gzip头 + deflate编码的实际内容 + gzip尾<br />zlib = zlib头 + deflate编码的实际内容 + zlib尾<br />因最近在做一

wy_2012的专栏 7865

600份国家自然基金申报书--模板

600份国家自然基金申报书--模板

需要远程指导仿真实验、代码有问题的,请后台私信或者关注公众号 4189

RFC1951 - DEFLATE Compressed Data Format Specification version

http://www.faqs.org/rfcs/rfc1951.htmlRFC1951 - DEFLATE Compressed Data Format Specification versionNetwork Working Group P. DeutschRequest for Comme

zglcl008的专栏 1395

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

C语言HTTPS流中Deflate解压实战:zlib与OpenSSL集成指南

数据压缩是提升网络传输效率的核心技术之一,其中Deflate算法因其高压缩比和广泛适用性成为HTTP内容编码的标准。其原理基于LZ77压缩与霍夫曼编码的组合,在减少数据体积的同时保持解压速度。在工程实践中,结合TLS/SSL加密的HTTPS场景,需要处理加密流中的实时解压,这对内存管理和流式处理提出了更高要求。zlib库作为Deflate的权威实现,提供了完善的流式API,而OpenSSL则负责TLS层的加解密。通过将两者结合,可以在物联网设备通信、API网关等场景中,高效处理`Content-Encodi

356

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

deflate及gzip格式说明

前段时间公司的web服务器需要增加代理的gz解压功能。刚好手里有一些基础库,试着手动写了gz的解码函数。 开始以为很简单,后面读了不少相关的文档才发觉还是比较复杂的,花了不少时间才理清楚。 本文就对gz文件格式作一个完整的描述,因为复杂的部分主要是deflate(rfc1951)格式包的实现,所以本文也可以作为 deflate格式的参考简要说明。 为了本文理解上的准确性和rfc1951的标准...

forstudydown的专栏 2817

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Web服务器处理HTTP压缩之gzip、deflate压缩

gzip是一种数据格式,默认且目前仅使用deflate算法压缩data部分;Gzip是一种流行的文件压缩算法,现在的应用十分广泛,尤其是在Linux平台。当应用Gzip压缩到一个纯文本文件时,效果是非常明显的,大约可以减少70%以上的文件大小。这取决于文件中的内容。利用Apache中的Gzip模块,我们可以使用Gzip压缩算法来对Apache服务器发布的网页内容进行压缩后再传输到客户端浏览器。这样经过压缩后实际上降低了网络传输的字节数,最明显的好处就是可以加快网页加载的速度。

顺其自然~专栏 3599

Akka Streams 中的 Compression.inflate:基于 Deflate 的流式解压操作符完全指南

本文围绕 Akka Streams 的 `Compression.inflate` 操作符展开,它是官方文档 [inflate.md](https://link.gitcode.com/i/708ed160ed53ab50d611e34e99d06710) 所定义的流式解压能力:将一个由 `ByteString` 组成的流,按 Deflate 算法实时解压为另一个 `ByteString` 流。它

gitblog_00890的博客 197

为什么ZLIB压缩库能成为互联网世界的“隐形英雄“?

你是否想过,当你浏览网页、下载文件、甚至玩游戏时,有一个技术一直在默默工作,为你节省带宽、提高速度?这个技术就是ZLIB压缩库。作为互联网基础设施中不可或缺的一环,ZLIB已经存在了近三十年,却鲜为人知。今天,让我们一起揭开这个"隐形英雄"的神秘面纱。 ## 从数据膨胀到压缩革命:ZLIB如何改变游戏规则 在互联网早期,数据传输缓慢、存储空间昂贵是开发者面临的主要挑战。1995年,Jean-l

gitblog_00489的博客 1206

Go 语言标准库 compressflate 深度解析:DEFLATE 压缩算法的高效实现

在数据存储与传输领域,压缩算法是提升效率的关键技术。Go 语言标准库中的 `compress/flate` 包实现了 **DEFLATE** 压缩格式(RFC 1951),该算法结合了 **LZ77** 字典编码与 **Huffman 编码**,在压缩比和速度之间取得平衡,广泛应用于 gzip、zlib、PNG 等场景。本文将深入解析 `flate` 库的核心原理、API 设计及实战技巧,帮助开发者掌握这一底层压缩工具的高效用法。

Tekin 是深耕技术 20 年的全栈实战派专家,精通 Go/Python/Java 等多语言开发。博客专注技术原理与实战结合,深度解析 Python 高阶编程、Go 语言架构、数据库优化等硬核内容。涵盖并发编程、机器学习、云原生等前沿领域,通过真实案例拆 983

deflate——过时的网页压缩格式,最好禁用[转]

在设置GZip时,发现同时有个Deflate压缩设置,一开始并不了解Deflate压缩,于是便在启用GZip的同时,也启用了Deflate压缩。虽然同时设置GZip和Deflate压缩,并不影响网站的正常运行,并且在检测网站是否启用GZip时,返回的答案是已启用。但是我们能否不设置Deflate压缩呢?或者来说,需要禁用Deflate压缩呢?Deflate压缩又有什么好处和坏处?带着这一堆疑问,我...

weixin_30379531的博客 225

java inflaterinputstream_java – Android InflaterInputStream是否与流行的ZLIB Windows库相同?...

这里的数据格式是deflate,zlib和gzip都是相关的.>基数是deflate压缩数据格式,在RFC 1951中定义.因为它纯粹的形式通常是无用的,我们通常使用它周围的包装格式.> gzip压缩数据格式(RFC 1952)用于压缩文件.它由一个头部组成,该头部具有文件名和一些属性的空间,一个deflate数据流,以及最后的CRC-32校验和(4个字节). (规范中的一个流中也支持...

weixin_32687283的博客 117

deflate——过时的网页压缩格式,最好禁用

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_33890499的博客 264
上一篇: zlib数据格式分析(RFC-1950)
下一篇: PNG转YUV(自造轮子版)
Cross_Entropy
博客等级 码龄7年 69粉丝 45原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值