前言
通过上一章我们详细介绍了Xdelta3定义的三种增量指令和默认指令代码表后,本章来解析一下编码时生成的增量文件
。
由于内容比较多,所以这部分会分为两章来进行解析,这一章先对增量文件
的头部内容进行详细讲解,下一章将对增量文件
的解码窗口内容进行详细讲解。废话不多说,让我们开始吧!
VCDIFF编码格式
在进行增量文件
解析之前,我们有必要先了解一下增量文件
的编码格式——VCDIFF。
由于增量文件
经常需要在不同架构的机器之间进行传输,因此这是一种可移植的编码格式,它有以下几个特点:
- 压缩输出
在系列第一章时我们就说过,不含源文件的编码实质上就是数据压缩,其实即使是增量编码,其生成的增量文件
也经过压缩之后的大小。同时VCDIFF还支持使用外部压缩工具进行二次压缩,进一步压缩生成文件的大小。 - 数据可移植
该编码格式不涉及机器字节序和单词大小问题,这就允许数据在一台机器上编码,在另一台不同架构的机器上解码。 - 算法通用
解码算法独立于字符串匹配算法和windowing算法,这就允许使用不同的编码器编码,但都可以用相同解码器解码。 - 解码效率高
在不考虑二级编码器的情况下,解码算法运行的时间与目标文件的大小成比例,使用的空间与最大窗口大小成比例。VCDIFF与其他传统的压缩工具的不同之处在于,它只使用字节对齐的数据,从而避免了位级操作,在略微降低压缩效率的情况下提高了解码速度。
以上是VCDIFF格式文档《RFC3284》中的原文加上我自己的理解后翻译的,原文如下:
- Output compactness:
The basic encoding format compactly represents compressed or delta files. Applications can further extend the basic encoding format with “secondary encoders” to achieve more compression.- Data portability:
The basic encoding format is free from machine byte order and word size issues. This allows data to be encoded on one machine and decoded on a different machine with different architecture.- Algorithm genericity:
The decoding algorithm is independent from string matching and windowing algorithms. This allows competition among implementations of the encoder while keeping the same decoder.- Decoding efficiency:
Except for secondary encoder issues, the decoding algorithm runs in time proportionate to the size of the target file and uses space proportionate to the maximal window size. Vcdiff differs from more conventional compressors in that it uses only byte-aligned data, thus avoiding bit-level operations, which improves decoding speed at the slight cost of compression efficiency.
由于Xdelta3将数据压缩视为一种特殊的增量差分(不含源文件),因此为了方便讲解,我们后面的章节统一将使用VCDIFF格式编码的文件称为增量文件
,而不区分增量文件
和压缩文件。
VCDIFF格式的基本数据单位是字节,也就是说操作的最小单位是字节,而不是比特位,这点很重要。
通常来说一个字节占8位,所能表示的数字范围在0~255,超过255的数字VCDIFF使用Base-128
进行编码,关于Base-128
我之前写过一篇文章进行详细解释,不了解的朋友可以先去看下这篇文章《浅析Base-128编码约定》。简单说明一下,就是超过255的数字将被拆分成多个字节编码,每个字节中最高的比特位当作标志位,不表示数值,解码时通过将多个字节拼接在一起还原该数字。
我们约定不超过255(即可以用一个字节表示)的数字,称为byte(字节);超过255(即需要用多个字节表示)的数字,称为integer(整数);之后的讲解中我们都将保持这个约定。
增量文件头部解析
铺垫了这么久,终于回到主题了。要想了解增量文件
的内容,首先就要先了解其结构,增量文件
是以一个Header部分开始,也就是我们常说的文件头部,Header之后紧跟着一连串的Window部分,这部分我打算放在下一章进行详细讲解,本章先讲解Header部分。
Header部分的结构如下所示,中括号表示该字段是可选的:
Header部分
Magic1 - byte = 0xD6 = 'V'+128
Magic2 - byte = 0xC3 = 'C'+128
Magic3 - byte = 0xC4 = 'D'+128
Version - byte = 0x00
Hdr_Indicator - byte
|-[二次压缩器ID] - byte
|-[代码表长度] - integer
|-[代码表数据]
|-[应用程序头长度] - integer
|-[应用程序头信息]
Magic字和版本号
Header部分的前三个字节是VCDIFF格式文件的Magic字,其值分别为’V’、‘C’、'D’的ASCII码,并将每个字节的最高位(MSB)置1。第四个字节是VCDIFF的版本号,目前固定为0。当解码增量文件
时会先检查Magic字和版本号,代码实现如下:
//VCDIFF文件格式的Magic字宏定义
#define VCDIFF_MAGIC1 0xd6 /* 1st file byte 'V' = 01010110,D6 = 11010110 */
#define VCDIFF_MAGIC2 0xc3 /* 2nd file byte 'C' = 01000011,C3 = 11000011 */
#define<