Java Deflater中提到的策略选项起源于ZLIB(C)实现的
RFC 1950和DEFLATE(
1951),我相信它们存在于几乎所有实现DEFLATE的压缩库中。
要理解它们的含义,您需要了解一些关于
DEFLATE的知识。压缩算法结合了LZ77和Huffman编码。基本原理如下:
LZ77压缩通过查找重复的数据序列来实现。实现通常使用大小在1k到32k之间的"滑动窗口",以跟踪前面的数据。对于原始数据中的任何重复项,LZ77压缩将插入一个"回溯引用",而不是将重复的数据插入输出。想象一下回溯引用说"在此处插入您在8293个字节之前看到的相同数据,共17个字节"。回溯引用被编码为这对数字:长度 - 在本例中为17 - 和距离(或偏移量) - 在本例中为8293。
Huffman编码用代码替代实际数据。当数据为X时,Huffman代码为Y。如果替代比原始数据短,则显然有助于压缩。(在吉姆·凯瑞的电影
Yes Man中,有一个反例,当Norm使用"Car"作为Carl的简称时,卡尔指出Carl已经很短了。)Huffman编码算法进行频率分析,并使用最短的替代方法替换最常出现的数据序列。
Deflate将这些组合起来,以便可以在LZ77反向引用上使用Huffman编码。各种DEFLATE / ZLIB压缩器上的策略选项只是告诉库如何权衡Huffman和LZ77。
通常意味着LZ77匹配停止于长度为5的位置。所以当文档说
使用(Filtered)处理由过滤器(或预测器)生成的数据,...过滤后的数据主要由具有某种随机分布的小值组成。
(摘自
zlib手册)
我的代码阅读表明它确实进行了LZ77匹配,但仅到五个或更少字节的序列。这就是文档所说的“小值”的含义。但数字5没有在文档中提到,所以不能保证该数字不会从版本到版本或从一个ZLIB / DEFLATE实现(如C版本和Java版本)改变。
HUFFMAN_ONLY
表示仅基于频率分析进行替换编码。 HUFFMAN_ONLY
很快,但对于大多数数据的压缩效果不是很好。除非您的字节值范围非常小(例如,如果您实际数据流中的字节仅占可能的 255 个值中的 20 个),或者在以大小为代价的压缩速度方面具有极端要求,否则 HUFFMAN_ONLY
将不是您想要的。
DEFAULT
将两种方法结合起来,这是作者预计对于大多数应用程序最有效的方式。
据我所知,在DEFLATE中没有仅使用LZ77的方法。也就是说,没有“LZ77_ONLY”策略。但是,您当然可以构建或获取自己的LZ77编码器,这将是“仅限LZ77”的。
请记住,策略永远不会影响压缩的正确性;它只影响压缩的操作和性能,无论是速度还是大小。
有其他方法可以调整压缩器。其中一种方法是设置LZ77滑动窗口的大小。在C库中,可以使用“窗口位”选项来指定此选项。如果您了解LZ77,则知道较小的窗口意味着较少的向后搜索,这意味着更快的压缩,但代价是会错过一些匹配。在进行压缩时,这通常是更有效的调节旋钮。
重点是,在80%的情况下,您不需要调整策略。您可能有兴趣调整窗口位,只是为了看看会发生什么。但只有在您的应用程序中完成所有其他必要的操作后才执行该操作。
参考资料:
DEFLATE是如何工作的,作者Antaeus Feldspar