11

我最近编写了一个名为zipzap的 zip 文件 I/O 库,但我正在努力从任意 zip 文件中正确解码 zip 条目文件名。

现在,PKWARE 规范指出:

D.1 ZIP 格式历来仅支持原始 IBM PC 字符编码集,通常称为 IBM Code Page 437...

D.2 如果未设置通用位 11,则文件名和注释应符合原始 ZIP 字符编码。如果设置了通用位 11,则文件名和注释必须支持 Unicode 标准,版本 4.1.0 或更高版本,使用 UTF-8 存储规范定义的字符编码形式...

这意味着符合标准的 zip 文件将文件名编码为 CP437,除非设置了 EFS 位,在这种情况下文件名是 UTF-8。

不幸的是,似乎很多 zip 工具要么没有正确设置 EFS 位(例如 Mac CLI、GUI zip),要么使用了其他一些编码,通常是默认的系统编码(例如 WinZip?)。如果您知道 WinZip、7-Zip、Info-Zip、PKZIP、Java JAR/Zip、.NET zip、dotnetzip 等如何对文件名进行编码以及它们在压缩时将“版本制作者”字段设置为什么,请告诉我.

特别是,Info-Zip 在解压缩时会尝试这样做:

  • 文件系统 = MS-DOS (0) => CP437
    • 除外:版本 = 2.5、2.6、4.0 => ISO 8859-1
  • 文件系统 = HPFS (6) => CP437
  • 文件系统 = NTFS (10) 和版本 = 5.0 => CP437
  • 否则,ISO 8859-1

如果我想支持检查或从任意 zip 文件中提取并在没有 EFS 标志的情况下对文件名编码进行合理尝试,我可以寻找什么?

4

2 回答 2

6

目前情况如下:

  • 大多数 Windows 实现使用 DOS (OEM) 编码
  • Mac OS zip 实用程序使用 utf-8,但它不设置 utf-8 位标志
  • *nix zip 实用程序静默使用系统编码

因此,唯一的方法是检查文件名是否包含类似 utf-8 字符的内容(检查 utf8 编码的描述 - 第一个字节应该是 110xxxxx,第二个 - 10xxxxxx 对于 2 字节编码的字符)。如果是正确的 utf8 字符串 - 使用 utf8 编码。如果不是 - 回退到 OEM/DOS 编码。

于 2012-11-11T12:09:37.463 回答
3

在不使用 EFS 标志的情况下确定文件名是否被编码为 UTF-8 的唯一方法是检查是否在其中一个字符中设置了高位。这可能意味着该字符是 UTF-8 编码的。但是,它仍然可能是另一种方式,因为 CP437 中的某些字符设置了高位并且不打算解码为 UTF-8。

我会坚持 PKWARE 应用笔记规范,而不是尝试符合现有的每个已知 zip 应用程序的解决方案。

于 2012-11-07T00:31:46.470 回答