GZIP源代码分析(三)

接上回

LZ77算法处理后,原始数据被归为两类数据对象:literal,即没有被匹配上的字节,以及(length, distance)二元组。Gzip按照扫描产生的先后顺序把它们有序保存在两个缓冲数组中l_bufd_buf,其中l_buf保存literallengthd_buf保存distance。由于literallength混杂保存在同一个数组中,因此还需要一个叫做flag_bufbitmap数据结构,用以确定l_buf中某个元素是literal还是length;也正是由于literallength是有序保存在一个数组中的,所以尽管原始数据被打散了,但其固有顺序还是被保留了下来。

在扫描过程中,当任意一个缓存满时,gzip就会把目前保存在这几个缓存中的数据作为一个压缩单元(称为block)输出,这样初步的压缩就完成了。

Lazy Match一种改进策略

之前所说的匹配策略是一种贪心算法,因为它每次都力争局部最优解,即每次都找最长匹配。但在稍大的范围内看,有时它的匹配结果并不那么优。比如对这样一个简单串做LZ77压缩:

ABCBCDEABCDE

当前扫描到第二个A,即灰底字开头。那么毫无疑问,会匹配到开头的ABC

ABCBCDEABCDE

然后接下来的DE因为没有可匹配串,就被作为两个literal了。

但是如果我们仔细观察会发现,如果当前串开头的A单独作为literal,那么后面的BCDE就可以被匹配上了:

ABCBCDEABCDE

压缩效果会比前一种好。

这就是Lazy Match“延迟匹配”。就是当前串找到最长匹配后,不急于敲定,而是继续找下一字节的最长匹配,如果长度比刚才还长,那么第一个字节会作为literal保存起来,但(长度-距离)二元组还是不敲定,再继续看下下字节的匹配情况,直到没有更好的选择为止。

Lazy Match可以提升压缩效果,但也意味着更长的压缩时间。在实际实现时,只要匹配长度足够长了,gzip就不会再lazy match下去。这个足够长的匹配长度是根据运行gzip命令时的压缩级别参数控制的,默认压缩级别是6,此时,lazy match的满意匹配长度是16字节长。

你可能感兴趣的:(GZIP源代码分析(三))