GZIP 的压缩原理与日常应用
每日一句诗词
loading...
loading...
GZIP 的压缩原理
Gzip是一种无损压缩工具,以将大块数据变得更小而闻名。
Gzip 压缩的原理是通过去除数据中的冗余信息,使用较短的代码表示频繁出现的字符或字符序列,从而减小数据文件的大小。这种压缩算法通常用于减少存储空间需求和加快网络传输速度。
LZ777
LZ77 的核心思路是如果一个串中有两个重复的串,那么只需要知道第一个串的内容和后面串相对于第一个串起始位置的距离 + 串的长度。
比如: ABCDEFGABCDEFH → ABCDEFG(7,6)H。7 指的是往前第 7 个数开始,6 指的是重复串的长度,ABCDEFG(7,6)H 完全可以表示前面的串,并且是没有二义性的。
LZ77 用 滑动窗口(sliding-window compression)来实现这个算法。具体思路是扫描头从串的头部开始扫描串,在扫描头的前面有一个长度为 N 的滑动窗口。如果发现扫描头处的串和窗口里的 最长匹配串 是相同的,则用(两个串之间的距离,串的长度)来代替后一个重复的串,同时还需要添加一个表示是真实串还是替换后的“串”的字节在前面以方便解压(此串需要在 真实串和替换“串” 之前都有存在)。
例如:缓冲区字符(ABCB)在滑动窗口的位移6位置找到AB,成功匹配到短语AB,将ABC编码为(6,2,C)
Huffman Coding
Huffman Coding 是大学课本中都会提到的算法。核心思路是通过构造 Huffman Tree 的方式给字符重新编码(核心是避免一个叶子的路径是另外一个叶子路径的前缀),以保证出现频路越高的字符占用的字节越少。
哈夫曼树的应用很广,哈夫曼编码就是其在电讯通信中的应用之一。广泛地用于数据文件压缩的十分有效的编码方法。其压缩率通常在20%~90%之间。
解压:Huffman Coding 之后需要维护一张 Huffman Map 表,来记录重新编码后的字符串,根据这张表,还原原始串也是非常高效的。
路径: 在一棵树中 ,从一个结点到另外一个结点的通路就称为 树的路径 .如图1.1 从根节点root到D节点之间的通路就是二叉树中的一条路径
压缩核心之 Deflate
GZIP 的核心是
Deflate
,在 RFC 1951 中被标准化,并且在当时作为 LZW 的替代品有了非常广泛的使用。
Deflate
是一个同时使用 LZ77 与 Huffman Coding 的算法.
如果想探究加解密的原理请看:《数据压缩技术原理与范例》
http传输应用
在 RFC 2016 中 GZIP 已经成为了规定的三种标准HTTP压缩格式之一。目前绝大多数的网站都在使用 GZIP 传输 HTML、CSS、JavaScript 等资源文件。
nginx开启
1 | # 开启 |
打开浏览器,访问你的网站,看 Chrome 的 Network,点 use larger request row,如果 Size 上有两个不一样大小的体积(如:222KB 和 613KB),则代表 GZIP 已经成功开启。
那浏览器又是如何和服务器配合的呢?
浏览器在请求资源的时候再 header 里面带上 accept-encoding: gzip
的参数。Nginx 在接收到 Header 之后,发现如果有这个配置,则发送 GZIP 之后的文件(返回的 header 里也包含相关的说明),如果没有则发送源文件。浏览器根据 response header 来处理要不要针对返回的文件进行解压缩然后展示。
缓存应用
我们在使用缓存中间件或者一些存储层的时候总会遇到存储的数据太庞大的问题。
解决办法:分片、压缩
分片就不多说了。
在java中有原生的GZIPInputStream实现,还可以使用Guava或者hutool去简单实现压缩。
1 | public static void main(String[] args) { |
原始字符占3379字节压缩后占963字节,释放了将近70%的空间,
我们简单了解原理后可以知道如果重复字符占比较多那么压缩效率会更大。