使用Java将非ASCII文件名添加到zip文件的最佳方法是什么,这样可以在Windows和Linux中正确读取文件?
这是一个改编自https://truezip.dev.java.net/tutorial-6.html#Example的尝试,它在Windows Vista中运行但在Ubuntu Hardy中失败.在Hardy中,文件名在文件夹中显示为abc-ЖДФ.txt.
import java.io.IOException; import java.io.PrintStream; import de.schlichtherle.io.File; import de.schlichtherle.io.FileOutputStream; public class Main { public static void main(final String[] args) throws IOException { try { PrintStream ps = new PrintStream(new FileOutputStream( "outer.zip/abc-åäö.txt")); try { ps.println("The characters åäö works here though."); } finally { ps.close(); } } finally { File.umount(); } } }
与java.util.zip不同,truezip允许指定zip文件编码.这是另一个示例,这次明确指定编码.IBM437,UTF-8和ISO-8859-1都不适用于Linux.IBM437适用于Windows.
import java.io.IOException; import de.schlichtherle.io.FileOutputStream; import de.schlichtherle.util.zip.ZipEntry; import de.schlichtherle.util.zip.ZipOutputStream; public class Main { public static void main(final String[] args) throws IOException { for (String encoding : new String[] { "IBM437", "UTF-8", "ISO-8859-1" }) { ZipOutputStream zipOutput = new ZipOutputStream( new FileOutputStream(encoding + "-example.zip"), encoding); ZipEntry entry = new ZipEntry("abc-åäö.txt"); zipOutput.putNextEntry(entry); zipOutput.closeEntry(); zipOutput.close(); } } }
Mnementh.. 10
ZIP中的文件条目的编码最初被指定为IBM代码页437.其他语言中使用的许多字符都不可能以这种方式使用.
在PKWARE规格是指问题,并增加了一点.但这是后来的补充(从2007年起,感谢Cheeso清理它,请参阅评论).如果设置了该位,则必须以UTF-8编码文件名条目.此扩展名在"附录D - 语言编码(EFS)"中描述,它位于链接文档的末尾.
对于Java来说,这是一个已知的错误,会遇到非ASCII字符问题.请参阅错误#4244499以及大量相关错误.
我的同事在将文件存储到ZIP中并在读取后解码之前,使用了文件名的解决方法URL-Encoding.如果你同时控制,存储和阅读,这可能是一种解决方法.
编辑:在错误的人建议使用Apache Ant的ZipOutputStream作为解决方法.该实现允许指定编码.
ZIP中的文件条目的编码最初被指定为IBM代码页437.其他语言中使用的许多字符都不可能以这种方式使用.
在PKWARE规格是指问题,并增加了一点.但这是后来的补充(从2007年起,感谢Cheeso清理它,请参阅评论).如果设置了该位,则必须以UTF-8编码文件名条目.此扩展名在"附录D - 语言编码(EFS)"中描述,它位于链接文档的末尾.
对于Java来说,这是一个已知的错误,会遇到非ASCII字符问题.请参阅错误#4244499以及大量相关错误.
我的同事在将文件存储到ZIP中并在读取后解码之前,使用了文件名的解决方法URL-Encoding.如果你同时控制,存储和阅读,这可能是一种解决方法.
编辑:在错误的人建议使用Apache Ant的ZipOutputStream作为解决方法.该实现允许指定编码.
在Zip文件中,根据PKWare拥有的规范,文件名和文件注释的编码是IBM437.2007年,PKWare扩展了规范,也允许使用UTF-8.这没有说明zip中包含的文件的编码.只有文件名的编码.
我认为所有工具和库(Java和非Java)都支持IBM437(它是ASCII的超集),并且更少的工具和库支持UTF-8.一些工具和库支持其他代码页.例如,如果您在上海运行的计算机上使用WinRar压缩某些内容,您将获得Big5代码页.这不是zip规范的"允许",但无论如何它都会发生.
用于.NET 的DotNetZip库可以使用Unicode,但是如果您使用Java,这对您没有帮助!
使用Java内置的ZIP支持,您将始终获得IBM437.如果您希望使用IBM437之外的其他内容存档,则使用第三方库,或创建JAR.
确实发生了奇迹,而Sun/Oracle确实解决了长期存在的bug/rfe:
现在可以在创建 zip文件/流时设置文件名编码(需要Java 7).
您仍然可以使用zip流的Apache Commons实现:http://commons.apache.org/compress/apidocs/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.html#setEncoding%28java.lang.String %29
在您的流上调用setEncoding("UTF-8")就足够了.