什么是 .zip 文件?
带有 .zip 扩展名的文件是可以保存一个或多个文件或目录的存档。存档可以对包含的文件应用压缩以减小 ZIP 文件的大小。 ZIP 文件格式于 1989 年 2 月由 Phil Katz 公开,用于实现文件和文件夹的归档。该格式是由 PKWARE, Inc. 创建的 PKZIP 实用程序的一部分。在 可用规范,许多公司将 ZIP 文件格式作为其软件实用程序的一部分,包括 Microsoft(自 Windows 7 起)、Apple (Mac OS X) 等。
ZIP 文件格式简史
ZIP 文件格式的历史可以追溯到 System Enhancement Associates (SEA) 对 PKWARE 提起诉讼的事件,因为 PKWARE 在未经其商标和产品外观和用户界面版权许可的情况下使用其 ARC 实用程序。在此之前,Phil Katz 重写了 SEA 的源代码,并发布了 PKXARC(ARC 提取器)和 PKARC(文件压缩器)作为基于 MS-DOS 的系统的免费软件。败诉后,PKWARE 无法再使用与 ARC 相关的任何东西。这就是创建新文件压缩的地方,命名为 ZIP,它是 PKWARE, Inc. 的 PKZIP 实用程序的一部分。
Katz 将 ZIP 文件格式规范发布到公共领域,同时保留对其压缩和提取实用程序(即 PKZIP)的专有权利。 ZIP 压缩系统曾经(并且现在)能够通过 32 位循环冗余校验 (CRC) 算法将文件存档在文件夹中以压缩文件尺寸。与 ARC 不同,.ZIP 文件夹包含一个目录文件,该目录文件扮演密码学家密码本的角色,包含呈现压缩文件所需的信息。
ZIP 中支持的压缩方法
根据 .ZIP 文件格式规范,支持以下压缩方法。
- 存储 - 意味着不压缩
- 收缩
- 减少(这意味着压缩因子从 1 级到 4 级)
- 内爆
- 放气
- 放气64
- BZIP2
- LZMA (EFS)
- WavPack
- PPMd 版本 I,修订版 1
DEFLATE 是一种常用的压缩方法,它是一种无损数据压缩算法,它使用 LZ77 和 Huffman 编码的组合,在 RFC 1951 中有详细说明。
ZIP 文件格式规范
ZIP 文件能够使用不同的压缩技术存储多个文件,同时支持在不进行任何压缩的情况下存储文件。每个文件都单独存储/压缩,这有助于提取它们或添加新文件,而无需对整个存档应用压缩或解压缩。
整体 ZIP 文件格式
每个 Zip 文件的结构如下:
ZIP 文件格式 |
---|
本地文件头 1 |
档案资料1 |
数据描述符 1 |
本地文件头 2 |
档案资料2 |
数据描述符 2 |
…… |
…… |
本地文件头 N |
文件数据 N |
数据描述符 N |
存档解密标头 |
归档额外数据记录 |
中央目录 |
ZIP 文件格式使用 32 位 CRC 算法进行归档。为了呈现压缩文件,ZIP 存档在其末尾保留一个目录,该目录保存包含文件的条目及其在存档文件中的位置。因此,它起着编码的作用,用于封装渲染压缩文件所需的信息。 ZIP 阅读器使用该目录来加载文件列表,而无需阅读整个 ZIP 存档。该格式保留了目录结构的双重副本,以提供更大的保护,防止数据丢失。
ZIP 存档中的每个文件都表示为一个单独的条目,其中每个条目由一个本地文件头和压缩文件数据组成。存档末尾的目录包含对所有这些文件条目的引用。 ZIP 文件阅读器应避免读取本地文件头,应从目录中读取各种文件列表。该目录是存档中有效文件条目的唯一来源,因为文件也可以附加到存档的末尾。这就是为什么如果阅读器从头开始读取 ZIP 存档的本地标头,它可能会读取无效(已删除)条目以及那些不属于从存档中删除的目录的一部分。
中央目录中文件条目的顺序不必与档案中文件条目的顺序一致。
ZIP 文件条目
ZIP 文件中的条目依次排列,其中每个条目包括:
- 本地文件头
- 可选的额外数据字段
- 用户数据(可选压缩/可选加密)
每个条目的本地文件头表示有关文件的信息,例如注释、文件大小和文件名。额外的数据字段(可选)可以容纳 ZIP 格式的可扩展性选项的信息。
本地文件头
本地文件头具有由多字节值组成的特定字段结构。所有值都以 little-endian 字节顺序存储,其中字段长度以字节为单位计算长度。 ZIP 文件中的所有结构对每个文件条目都使用 4 字节签名。中央目录签名的结尾是 0x06054b50,可以使用自己的唯一签名进行区分。以下是存储在本地文件头中的信息的顺序。
偏移量 | 字节 | 描述 |
---|---|---|
0 | 4 | 本地文件头签名#0x04034b50(读作小端数) |
4 | 2 | 提取所需的版本(最低) |
6 | 2 | 通用位标志 |
8 | 2 | 压缩方式 |
10 | 2 | 文件最后修改时间 |
12 | 2 | 文件最后修改日期 |
14 | 4 | CRC-32 |
18 | 4 | 压缩后的大小 |
22 | 4 | 未压缩大小 |
26 | 2 | 文件名长度 (n) |
28 | 2 | 额外字段长度 (m) |
30 | n | 文件名 |
30+n | m | 额外字段 |
中央目录文件头
偏移量 | 字节 | 描述 |
---|---|---|
0 | 4 | 中央目录文件头签名#0x02014b50 |
4 | 2 | 版本由 |
6 | 2 | 提取所需的版本(最低) |
8 | 2 | 通用位标志 |
10 | 2 | 压缩方式 |
12 | 2 | 文件最后修改时间 |
14 | 2 | 文件最后修改日期 |
16 | 4 | CRC-32 |
20 | 4 | 压缩后的大小 |
24 | 4 | 未压缩大小 |
28 | 2 | 文件名长度 (n) |
30 | 2 | 额外字段长度 (m) |
32 | 2 | 文件注释长度 (k) |
34 | 2 | 文件开始的磁盘号 |
36 | 2 | 内部文件属性 |
38 | 4 | 外部文件属性 |
42 | 4 | 本地文件头的相对偏移量。这是文件所在的第一个磁盘的开头与本地文件头的开头之间的字节数。这允许软件读取中央目录来定位 ZIP 文件中文件的位置。 |
46 | n | 文件名 |
46+n | m | 额外字段 |
46+n+m | k | 文件注释 |
中央目录记录结束
偏移量 | 字节 | 描述 |
---|---|---|
0 | 4 | 中央目录签名结束#0x06054b50 |
4 | 2 | 此磁盘的编号 |
6 | 2 | 中央目录开始的磁盘 |
8 | 2 | 此磁盘上的中心目录记录数 |
10 | 2 | 中央目录记录总数 |
12 | 4 | 中央目录的大小(字节) |
16 | 4 | 中央目录开始的偏移量,相对于存档的开始 |
20 | 2 | 评论长度 (n) |
22 | n | 评论 |