使用 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();
}
}
}
答案 0 :(得分:10)
ZIP中的文件条目的编码最初被指定为IBM代码页437.其他语言中使用的许多字符都不可能以这种方式使用。
PKWARE-specification引用问题并添加一点。但这是后来的补充(从2007年开始,感谢Cheeso清理它,请参阅评论)。如果设置了该位,则必须以UTF-8编码文件名条目。此扩展名在“附录D - 语言编码(EFS)”中描述,位于链接文档的末尾。
对于Java来说,这是一个已知的错误,会遇到非ASCII字符问题。请参阅bug #4244499以及大量相关错误。
我的同事在将文件存储到ZIP中并在阅读后解码之前,使用了文件名的解决方法URL-Encoding。如果您同时控制,存储和阅读,这可能是一种解决方法。
编辑:有人建议使用Apache Ant的ZipOutputStream作为解决方法。此实现允许指定编码。
答案 1 :(得分:8)
在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。
答案 2 :(得分:8)
奇迹确实发生了,而Sun / Oracle确实修复了长期存在的bug / rfe:
现在可以set up filename encodings upon creating压缩文件/流(需要Java 7 )。
答案 3 :(得分: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”)就足够了。
答案 4 :(得分:3)
快速查看TrueZIP manual - 他们推荐使用JAR格式:
它使用UTF-8进行文件名编码 和评论 - 不像ZIP,只有 使用IBM437。
这可能意味着API正在使用java.util.zip包来实现它;该文档声明它仍在使用ZIP format from 1996。直到2006年,PKWARE .ZIP File Format Specification才添加了Unicode支持。
答案 5 :(得分:0)
它真的失败了还是只是一个字体问题? (例如,字体对于那些字符有不同的字形)我在Windows中看到类似的问题,渲染“破坏”,因为字体不支持字符集,但数据实际上是完整和正确的。
答案 6 :(得分:0)
非ASCII文件名在ZIP实现中不可靠,最好避免使用。没有规定在ZIP文件中存储字符集设置;客户倾向于猜测“当前的系统代码页”,这不太可能是你想要的。客户端和代码页的许多组合都可能导致文件无法访问。
抱歉!