添加非ASCII文件名在Java拉链(Add non-ASCII file names to zip

2019-06-24 13:27发布

What is the best way to add non-ASCII file names to a zip file using Java, in such a way that the files can be properly read in both Windows and Linux?

Here is one attempt, adapted from https://truezip.dev.java.net/tutorial-6.html#Example, which works in Windows Vista but fails in Ubuntu Hardy. In Hardy the file name is shown as abc-ЖДФ.txt in file-roller.

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();
        }
    }
}

Unlike java.util.zip, truezip allows specifying zip file encoding. Here's another sample, this time explicitly specifiying the encoding. Neither IBM437, UTF-8 nor ISO-8859-1 works in Linux. IBM437 works in 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();
        }
    }
}

Answer 1:

对于文件条目的ZIP编码最初被指定为IBM的代码页437.在其他语言中使用的很多人物都不可能使用这种方式。

在PKWARE规格是指问题,并增加了一点。 但是,这是一个后来添加(从2007年,由于Cheeso清理,截至见注释)。 如果该位被设置,文件名进入在UTF-8编码。 这个扩展中描述的“附录d - 语言编码(EFS)”,即在链接的文档的末尾。

对于Java这是一个已知的错误,进入非ASCII字符的麻烦。 见错误#4244499和大量相关的错误。

我的同事作为变通方法的URL编码的文件名,将它们存储到ZIP和解码读取它们前后。 如果你同时控制,存储和读取,这可能是一个解决办法。

编辑:在错误的人建议使用ZipOutputStream的是Apache Ant的解决方法。 此实现允许编码规范。



Answer 2:

在Zip文件,根据PKWARE所拥有的规格,文件名和文件注释的编码是IBM437。 2007年PKWARE扩展规范也允许UTF-8。 这只字未提包含的zip中的文件的编码。 文件名的唯一编码。

我认为所有的工具和库(Java和不支持Java)支持IBM437(这是ASCII的一个超集),以及较少的工具和库支持UTF-8。 一些工具和库支持其他代码页。 例如,如果你在上海运行的计算机上用winrar压缩的东西,你会得到Big5编码页。 这不是“允许”被压缩规范,但无论如何它发生。

该DotNetZip库.NET确实Unicode的,当然它不能帮助你,如果你使用的是Java!

使用ZIP的Java的内置支持,你总是会得到IBM437。 如果你想比其他IBM437东西归档,然后使用第三方库,或创建一个JAR。



Answer 3:

奇迹发生确实和Sun /甲骨文没有真正解决长期居住的错误/ RFE:

现在有可能在创建设置文件名的编码压缩文件/流( 需要Java 7)。



Answer 4:

您仍然可以使用Apache Commons实施拉链流: http://commons.apache.org/compress/apidocs/org/apache/commons/compress/archivers/zip/ZipArchiveOutputStream.html#setEncoding%28java.lang.String %29

您流调用setEncoding(“UTF-8”)就足够了。



Answer 5:

从快速浏览一下TrueZIP 手册 -他们建议JAR格式:

它采用UTF-8的文件名编码和意见 - 与邮政编码,其中只有使用IBM437。

这可能意味着该API使用java.util.zip包的执行; 该文件指出,它依然使用的是ZIP格式,从1996年 。 Unicode支持未添加到PKWARE .ZIP文件格式规范 ,直到2006年。



Answer 6:

它是否真的失败或只是一种字体的问题? (例如,字体为那些charcodes不同的字形)我见过类似的问题在Windows中,其中呈现“爆发”,因为字体不支持的字符集,但数据实际上是完整和正确的。



Answer 7:

非ASCII文件名不能跨邮编实现可靠,最好避免。 没有规定用于存储在ZIP文件字符集设置; 客户往往与“当前系统代码页”,这是不太可能你想要的猜测。 客户和代码页的多种组合可能会导致无法访问的文件。

抱歉!



文章来源: Add non-ASCII file names to zip in Java