天天看点

GZIP压缩原理分析(18)——第五章 Deflate算法详解(五09) 算法分析(03) 格式说明(02) 存储类型

存储类型(store)的格式如下,

   0     1     2    3     4...

+---+---+---+---+================================+

|    LEN   |  NLEN  |... LEN bytes of literal data...|

+---+---+---+---+================================+

每个‘+---+’代表一个字节,‘+==============+’代表一定数量的字节。LEN表示本块共含有多少个字节的数据(该块没有压缩,所以对应的数据仍然是字节流),NLEN是LEN的补充(其实我也不知道NLEN是怎么使用的,没怎么见过,这里贴上RFC原文“NLEN is the one's complement of LEN”)。后面就是被存储的原始数据了。

很明显,存储类型全部是字节流,块首部只有三比特,而且块首部后面紧跟着就是以该格式表示的存储类型的数据了,对于这种情况,实际的处理方式就是,块首部后面如果还不够一个字节,那么剩下的不够一个字节的那几个比特就全部忽略,实际的数据从一个全新的字节开始。简而言之,就是块首部是比特流而被存储的数据是字节流,这两种流要拼在一起,为了让比特流是字节的整数倍,因此可能要浪费几个比特。例如,块首部只用了一个字节的三比特,还有五比特可用,这个时候,如果使用存储类型,那么这五比特就浪费了,数据会从下一个字节开始。如下图所示,

GZIP压缩原理分析(18)——第五章 Deflate算法详解(五09) 算法分析(03) 格式说明(02) 存储类型

原始文件a.txt中只有字符a,整个文件只有1个字节,使用gzip压缩,该文件使用的压缩方式是存储,去掉gzip文件头和文件尾,就只剩下以下内容“01 01 00 FE FF 61”。其中,“61”就是字符a,将其他内容转换成二进制就是“0000 0001 0000 0001 00000000 1111 1110 1111 1111”。看第一个字节,“0000 0001”,这是内存中实际存储的方式,我们要从右往左找块首部(这种方式只针对被压缩之后的二进制码流,该方法后面要经常使用),就是“001”,从右往左读就是“100”,第一位是1,表示这是最后一个压缩块,后面两位是零,表示这里使用存储的方式。这个字节还剩下五比特,全部是零了,这五比特没有任何含义,完全是为了给块首部补齐一个字节。可以看到,后面的四个字节,其实就是LEN和NLEN,这里要注意高低字节的问题(大小端),LEN其实是“00 01”,NLEN是“FF FE”,CRC32是“E8 B7 BE 43”,原始文件长度是“00 00 00 01”,提示,这几个数可不是二进制码流,每个字节内部可不能从右往左读,比如把“0x43”读成“0xC2”,切记切记!!!