正确解码zip文件条目名称--CP437、UTF-8还是其他?

17

我最近写了一个名为zipzap的zip文件输入输出库,但我正在努力从任意的zip文件中正确解码zip入口文件名。

现在,PKWARE规范指出:

D.1 ZIP格式历史上只支持原始IBM-PC字符编码集,通常称为IBM代码页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标志的情况下尝试进行文件名编码的合理处理,我应该寻找什么?

2个回答

7
目前情况如下:
  • 大多数Windows实现使用DOS(OEM)编码
  • Mac OS zip工具使用utf-8,但它不设置utf-8位标志
  • *nix zip工具默默地使用系统编码
因此,唯一的方法是检查文件名是否包含类似于utf-8字符的内容(检查utf8编码的描述-第一个字节应为110xxxxx,第二个字节应为10xxxxxx,用于2字节编码的字符)。如果它是正确的utf8字符串-使用utf8编码。如果不是,则回退到OEM / DOS编码。

4

在不使用EFS标志的情况下确定文件名是否以UTF-8编码的唯一方法是检查一个字符中是否设置了高位比特。这可能意味着该字符已UTF-8编码,但也可能相反,因为CP437中有一些字符的高位比特被设置,但实际上并不应当解码为UTF-8。

我建议遵循PKWARE应用程序规范,而不是尝试符合所有已知的zip应用程序的解决方案。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接