正确解码zip条目文件名 - CP437,UTF-8或?

Gle*_*Low 10 zip jar 7zip zipfile winzip

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

现在,PKWARE规范指出:

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

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

这意味着符合的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标志的情况下合理地尝试文件名编码,我还能找到什么?

Nic*_*sky 6

目前情况如下:

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

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


Nat*_*iri 4

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

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