zip是我们日常生活中很经常用到的一种归档压缩格式/工具,这是Phil Katz在1989年的一种压缩格式,至今经过多种改良,基本的格式规范依然生效,今天我就PKZip总结一下ZIP的格式及各字段含义。
一般来说,zip的格式由三部分组成
- File Entry:压缩文件内容源数据
- Central Directory:目录源数据,用于描述File Entry中的文件,放于文件尾部,方便以后添加新数据
- End of Central Directory:结束Central Directory,用于描述整个zip文件的总体信息
以下分开几个部分描述,以下都基于010editor,以及sample,zip文件的内容如下
.
├── zipentry
│ ├── file_2.txt
│ └── file_3.txt
└── file_1.txt
File Entry
对于sample来说,存在三个文件,但对于zip来说,目录其实也算是一个文件,且看010editor解析出来的file entry。
存在四个File Entry区域,每一个区域代表一个文件,其中,文件夹zipentry也被当作一个文件对待,每一个文件的结构如下:
每一个字段的含义如下:
offset | bytes | desc |
---|---|---|
0 | 4 | 文件头标识,固定为 0x04034b50,使用小端方式读取(PK即为作者PhilKatz的名字缩写) |
0 | 2 | 解压文件的最低版本号 |
6 | 2 | 通用位标记,见后 |
8 | 2 | 压缩方法,见后 |
10 | 2 | 文件最后修改时间 |
12 | 2 | 文件最后修改日期 |
14 | 4 | 采用crc32算法以0xdebb20e3为算子计算文件数据的值 |
18 | 4 | 压缩后的文件大小 |
22 | 4 | 未压缩时的文件大小 |
26 | 2 | 文件名长度 |
28 | 2 | 扩展区长度 |
30 | n | 文件名 |
30+n | m | 扩展区 |
如图中的例子,由于文件的内容都是比较简单且基本不存在重复的字符串的,所以使用方式使用了COMP_STORED的方式,即不压缩,只归档;frData内为压缩后的数据内容,由于内容实际上没压缩,所以可以很清楚地显示到file_1.txt的内容,当存在压缩时,即为压缩后的数据。对于数值大小,如果没有带”h”的,都表示是十进制数据。
对于目录类型的文件,其实也大同小异,不过就一些字段(如压缩大小,crc32等)就不需要计算了
file entry的内容就是这么简单。
Central Directory
centtral directory包含压缩文件和加密数据的更多元数据和Zip64的信息,也包含跨压缩文件的信息(如一个压缩文件分为几个)。sample中的结构如下:
同样存在四个区域,一一对应上边的File Entry,打开其中一个
各字段解析如下:
offset | bytes | desc |
---|---|---|
0 | 4 | 头标识,固定为0x02014b50 |
4 | 2 | 压缩所用的pkware版本,见下 |
6 | 2 | 能够解压的最低版本 |
8 | 2 | 通用位标记,见下 |
10 | 2 | 压缩方法,见下 |
12 | 2 | 文件最后修改时间 |
14 | 2 | 文件最后修改日期 |
16 | 4 | CRC32校验码 |
20 | 4 | 压缩后大小 |
24 | 4 | 压缩前大小 |
28 | 4 | 文件名长度 |
30 | 2 | 扩展域长度 |
32 | 2 | 文件注释长度 |
34 | 2 | 文件开始位置的磁盘编号(这个值不知道是表示什么) |
36 | 2 | 内部文件属性,内容见下 |
38 | 4 | 外部文件属性,依赖于外部的文件系统 |
42 | 4 | 本地文件header的相对位置,这里会指向FileEntry的头 |
46 | n | 目录文件名 |
46+n | m | 扩展域 |
46+n+m | k | 文件注释内容 |
End of Central Directory Record
目录结束标识存在 于整个归档包的未尾,用于标记压缩的目录数据结束了。sample的结构如下:
各字段解析如下:
offset | bytes | desc |
---|---|---|
0 | 4 | 头标识,固定为0x06054b50,小端 |
4 | 2 | 当前磁盘编号 |
6 | 2 | central directory开始位置的磁盘编号 |
8 | 2 | 该磁盘上记录的central directory数目,如果是同一磁盘,则为全部的central directory数目,sample为4 |
10 | 2 | central directory结构总个数,sample为4 |
12 | 4 | central directory的大小,这里会算上整个central directory的大小,sample为200+65-e4=385 |
16 | 4 | central directory相对于整个文件开头的位置,sample为0xe4 |
20 | 2 | 注释长度 |
22 | n | 注释内容,这个注释是整个压缩文件的注释,与central directory中的不一样,那个是相对于文件目录的 |
扩展
通用位标记
0 | 1+2 | 3 | 4 | 5 | 6 | 7+8+9+a | b | c | d | e+f |
---|---|---|---|---|---|---|---|---|---|---|
压缩的文件 | 加密选项 | 数据描述 | 压缩增强 | 压缩patch数据 | 强加密 | 没用 | 语言编码 | 保留 | header掩码 | 保留 |
压缩方法
编码 | 方法 | 编码 | 方法 |
---|---|---|---|
00 | 没压缩 | 01 | shrunk |
02 | reduced with compression factor 1 | 03 | reduced with compression factor 2 |
04 | reduced with compression factor 3 | 05 | reduced with compression factor 4 |
06 | imploded | 07 | 保留 |
08 | deflated | 09 | enhanced deflated |
10 | PKWare DCL imploded | 11 | 保留 |
12 | BIZ2 | 13 | 保留 |
14 | LZMA | 15 | 保留 |
16 | 保留 | 17 | 保留 |
18 | IBM TERSE | 19 | IBM LZ77Z |
98 | PPMd version I,Rev 1 |
编码版本
编码 | 版本 | 编码 | 版本 |
---|---|---|---|
0 | MS-DOS | OS/2 | |
1 | Amiga | 2 | OpenVMS |
3 | UNIX | 4 | VM/CMS |
5 | Atari ST | 6 | OS/2 H.P.F.S |
7 | Macintosh | 8 | Z-System |
9 | CP/M | 10 | NTFS |
11 | MVS(OS/390-Z/OS) | 12 | VSE |
13 | Acorn Risc | 14 | VFAT |
15 | alternate MVS | 16 | BeOS |
17 | Tandem | 18 | OS/400 |
19 | OS/X(Darwin) | 20-255 | 保留 |
内部属性
0 | 1 | 2 | 3-f |
---|---|---|---|
标识为ASCII/text文件 | 保留 | 一个控制位,记录之前的的逻辑记录 | 未用 |
参考
The structure of a PKZip file
Zip (file format))
ZIP压缩算法详细分析及解压实例解释
Zip算法实现