Zip 规范(历史上)没有指定用于嵌入文件名和 cmets 的字符编码,最初的 IBM PC 字符编码集,通常称为 IBM Code Page 437,应该是唯一的编码支持的。 Jar 规范同时明确指定使用 UTF-8 作为编码对 Jar 文件中的所有文件名和 cmets 进行编码和解码。为此,我们的 java.util.jar 和 java.util.zip 实现严格遵循 Jar 规范,在处理 Jar/Zip 文件中存储的文件名和 cmets 时使用 UTF-8 作为唯一编码。
后果?基于 java.util.jar/zip 的工具无法访问由“传统”ZIP 工具创建的 ZIP 文件,反之亦然,如果文件名包含 Cp437 之间不兼容的字符(作为替代,工具可能只使用默认平台编码)和 UTF-8
对于大多数欧洲人来说,你是“幸运的”:-) 你只需要避免“少数”字符,例如元音变音(好吧,我只是在开玩笑),但对于日语和中文来说,大多数的字符只是运气不好。这就是为什么 bug 4244499 多年来一直是 Top 25 Java Bugs 中的第一名。该错误不再在列表中:-) 它终于在 OpenJDK 7, b57 中“修复”了。我仍然保留快照作为自己的记录/kudo:-)
JDK7 b57 中的解决方案(我会使用“解决方案”而不是“修复”)是在一组新的 ZipInputStream ZipOutStream 和 ZipFile 构造函数中引入特定的“字符集”作为参数,如下所示。
ZipFile(文件,字符集)
ZipInputStream(InputStream, Charset)
ZipOutputStream(OutputStream, Charset)
使用这些新的构造函数,应用程序现在可以通过使用特定编码创建的 ZipInputStream 或 ZipFile 对象访问那些非 UTF-8 的 ZIP 文件,或者通过新的 ZipOutputStream(os, charset) 构造函数,如果需要的话。
zip 是 Jar 工具的精简版,带有“-encoding”选项,以支持条目名称和注释的非 UTF8 编码,它可以作为如何使用新 API 的演示(我用过它作为单元测试)。我还在和自己争论,在 Jar 工具中正式引入“-encoding”是否是个好主意......