在zip存档中使用Unicode字符作为文件名

Mad*_*ddy 8 java zip file

我正在压缩文件名包含一些特殊字符,如PéréquationLESHOPITAUX NEUFS.xls到另一个文件夹,比如temp.

我能够压缩文件,但问题是文件名自动更改为 P +¬r+¬quationLESHOPITAUX NEUFS.xls.

如何在zip存档中支持文件名的unicode字符?

Adr*_*tti 16

这取决于您用于创建存档的代码.在的Java压缩类不是很灵活,因为你需要.

您可以使用Apache Commons Compress.Michael Simons写了这段很好的代码:

ZipArchiveOutputStream ostream = ...; // Your initialization code here
ostream.setEncoding("Cp437"); // This should handle your "special" characters
ostream.setFallbackToUTF8(true); // For "unknown" characters!
ostream.setUseLanguageEncodingFlag(true);                               
ostream.setCreateUnicodeExtraFields(
    ZipArchiveOutputStream.UnicodeExtraFieldPolicy.NOT_ENCODEABLE);
Run Code Online (Sandbox Code Playgroud)

如果您正在使用Java 7,那么您最终CharsetZipOutputStream构造函数上有一个参数(可以是UTF-8)

无论如何,最大的问题是许多实现不理解Unicode编码,因为原始 ZIP文件格式是ASCII并且没有Unicode的官方标准.有关详细信息,请参阅此帖子.

  • 在流上调用setEncoding("UTF-8")或将其作为FileOutputStream构造函数的参数提供.无论如何不要忘记答案中指出的兼容性问题! (2认同)
  • 如果您不能使用Java 7,您可以使用Apache Common Compress之类的第三方库 (2认同)

dha*_*ram 7

Zip规范(历史上)没有指定用于嵌入式文件名和注释的字符编码,原始IBM PC字符编码集(通常称为IBM Code Page 437)应该是唯一支持的编码.Jar规范同时明确指定使用UTF-8作为编码来解码和解码Jar文件中的所有文件名和注释.我们的java.util.jar和java.util.zip实现严格遵循Jar规范,在处理存储在Jar/Zip文件中的文件名和注释时,使用UTF-8作为唯一编码.

后果?基于java.util.jar/zip的工具无法访问由"传统"ZIP工具创建的ZIP文件,反之亦然,如果文件名包含Cp437之间不兼容的字符(作为替代方案,工具可能只是使用默认平台编码)和UTF-8

对于大多数欧洲人来说,你是"幸运的":-)你只需要避免使用"少数"字符,例如变音符号(好吧,我只是在开玩笑),但对于日语和中文,大多数字符简直是运气不好.这就是为什么bug 4244499多年来一直是Top 25 Java Bugs的第一名.该错误已不在列表中:-)它最终在OpenJDK 7,b57中"修复".我仍然保留快照作为我自己的记录/工作:-)

JDK7 b57中的解决方案(我将使用"解决方案"而非"修复")是在一组新的ZipInputStream ZipOutStream和ZipFile构造函数中引入特定的"charset"作为参数,如下所示.

ZipFile(File,Charset)

ZipInputStream(InputStream,Charset)

ZipOutputStream(OutputStream,Charset)

使用这些新构造函数,应用程序现在可以通过ZipInputStream或使用特定编码创建的ZipFile对象访问这些非UTF-8 ZIP文件,或者通过新的ZipOutputStream(os,charset)构造函数创建以非UTF-8编码的Zip文件,如有必要.

zip是Jar工具的精简版本,带有"-encoding"选项,支持非UTF8编码的条目名称和注释,它可以作为如何使用新API的演示(我用它作为一个单元测试).我还在和自己辩论,如果在Jar工具中正式引入"-encoding"是个好主意...