GZIP压缩原理分析(12)——第五章 Deflate算法详解(五03) 预备知识(02) 压缩“窗口”概念

压缩的过程使用了“窗口”这一概念。压缩时,将需要处理的数据拷贝到窗口中,然后直接在窗口中分析并处理这些数据。这个窗口就好比一张工作台,每次把要处理的东西放到这张工作台上,人们站在工作台旁边收拾这些数据,等到快收拾完的时候(还没收拾完!!!),再去库房把后面的数据取到工作台上……基本就是这样一个过程。需要注意的是,窗口的概念是贯穿压缩始终的,真的就像个工作台一样。

 

在源码中,指针window指向一块内存,大小为64KB,这就是“窗口”了。该窗口由两部分构成,每部分大小为WSIZE,每个WSIZE大小为32KB。压缩开始后,首先要读一个窗口(读64KB)的待压缩数据到这个窗口中,如果没有这么多待压缩数据,那就把当前所有的待压缩数据全部读到这个窗口中。接下来的压缩过程就完全针对这个窗口中的数据展开。窗口按照大小被分成了两个WSIZE,按照功能,窗口也同时被分成“查找缓冲区+先行缓冲区”两部分。如下图(a)和(b)所示,图(a)是需要压缩的全部原始数据,压缩开始后,从原始数据中读取整整一个window_size的数据到window这块内存中,如图(b)所示。此时这块内存按照大小被分为两块,每块大小为WSIZE;按照功能被分为两部分,查找缓冲区和先行缓冲区。

 

压缩会逐字节处理先行缓冲区中的数据,每处理一个字节,先行缓冲区就减小一个字节,同时查找缓冲区就扩大一个字节,如图(b)所示。压缩刚开始的时候,按功能来分,此时窗口中只有先行缓冲区而没有查找缓冲区,随着压缩的进行,查找缓冲区越来越大(但是最大不超过32KB,而先行缓冲区越来越小。

 (提示,这只是示意图,图中所示的尺寸只是为了在这里起到一个说明的作用)

 随着压缩的进行,先行缓冲区越来越小而查找缓冲区越来越大,直到先行缓冲区只剩MIN_LOOKAHEAD(这是源码中使用的一个宏,这里提前透露一下)这么点时,如图(c)所示,此时就要做一些特殊操作了。

 

当先行缓冲区只剩MIN_LOOKAHEAD这么点时,此时先行缓冲区的第一个字节在WSIZE2中。从这个字节开始,跨过查找缓冲区中一个WSIZE大小的区间(连续的32KB),仍然无法到达window的起始位置(在图c中是显而易见的)。和WSIZE相比,MIN_LOOKAHEAD简直小到不值一提,所以从先行缓冲区第一个字节开始在查找缓冲区中找连续的32KB,那么这32KB中的绝大部分数据都在WSIZE2中,即,有(WSIZE - MIN_LOOKAHEAD)数据在WSIZE2中,而只有MIN_LOOKAHEAD这么点数据在WSIZE1中。而且在查找缓冲区中寻找匹配串的时候,匹配串的出现位置通常不会跑到那么远。基于以上原因(MIN_LOOKAHEAD很小而且匹配串不会出现在那么远的地方),忽略掉WSIZE1中MIN_LOOKAHEAD数量的数据是完全没有问题的,并且在WSIZE1中(WSIZE1 - MIN_LOOKAHEAD)数量的数据压根不在查找缓冲区里!!!所以,此时可以说,WSIZE1已经没用了!

 

既然WSIZE1中的数据已经没用了,那就把WSIZE2中的所有数据拷贝到WSIZE1中,再从原始待压缩数据中读取一个WSIZE的数据并将其拷贝到WSIZE2中,如图(c)所示。这就是压缩中窗口的使用原理。

 

窗口中的数据只是用来“扫描”用的,也就是说,窗口中的数据是用来分析的,不会改变窗口中的数据,当然,将WSIZE2的数据拷贝到WSIZE1的过程不能算作“改变”。窗口中的数据用来分析,而分析结果,也就是实际的压缩结果,会被存储到另外一块内存中并输出。这个过程后面还会具体分析,这里提一下,为后面做铺垫。

 

这里给查找缓冲区下个定义,后面就直接使用了。查找缓冲区:从先行缓冲区第一个字节开始,往已经完成处理的字节的方向算起,连续的一串数据称为查找缓冲区,查找缓冲区大小不超过32KB注意,与其他博客不同,我这里故意避免提到“向前”以及“向后”的说法,因为向前与向后理解起来太容易混乱。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章