如何向zip文件添加utf-8名称的zip条目

7
我有一个方法,可以将输入流添加到zip作为一个目录项:
private void addToZip(InputStream is, String filename) throws Exception {
    try {
        ZipEntry zipEntry = new ZipEntry(filename);
        zos.putNextEntry(zipEntry);
        byte[] bytes = new byte[1024];
        int length;
        while ((length = is.read(bytes)) >= 0) {
            zos.write(bytes, 0, length);
        }
        zos.closeEntry();
    } finally {
        IOUtils.closeQuietly(is);
    }
}

当文件名包含UTF-8字符(如áé...)时,出现问题。在zip文件中,它将被保存为?????,当我在ubuntu 12.10上解压缩时,它看起来像:N├бstroje而不是Nástroje
对于这个例子,我使用的是jdk6,但现在我也尝试了jdk7:
zos = new ZipOutputStream(fos, Charset.forName("UTF-8"));

但是一直没有成功。
我也尝试了Apache Commons Zip并设置编码,但也没有成功。
那么我该如何将文件名包含Unicode符号的文件添加到zip中呢?

我以前也遇到同样的问题。我使用了非Unicode字符集(Cp866),该字符集是特定于当地语言的,这样做可以解决问题。 - user784540
所以,我应该将“Nástroje”保存为“Nastroje”?这是最后的选择...你如何转换它? - hudi
该应用程序旨在在Windows系统中运行。我使用了Cp866编码,以支持zip存档中的俄语文件名并在查看zip文件内容时正确显示它们。而且它起作用了。是否有一种非Unicode字符集,可以支持您的语言符号?请尝试使用它,而不是utf-8。 - user784540
是的:iso-8859-2,但是当我使用它时,á会转换为c。 - hudi
很抱歉,我不知道如何克服那个问题。 - user784540
没关系。我解决了我的问题,但是我不知道它为什么有效 :) - hudi
2个回答

4

看起来这行代码解决了我的问题:

        zos.setCreateUnicodeExtraFields(UnicodeExtraFieldPolicy.ALWAYS);

有人能解释一下这是在做什么,为什么它能起作用吗?


2
Unicode Extra Fields是zip格式的扩展,用于在条目头中使用附加自定义字段来存储文件名的UTF-8版本,并与默认本地编码版本一起使用。支持此扩展的存档解包器将优先使用来自额外字段的UTF-8名称而不是标准名称字段。 - Ian Roberts
我找不到ZipOutputStream中的setCreateUnicodeExtraFields方法。 - Bogdan Samondros
@BogdanSamondros 这是一个Apache Ant API ZipOutputStream。 - chubbsondubs

3

Zip压缩文件默认使用DOS(OEM)代码页来存储文件名。Linux/Unix实现在解压时使用系统代码页。Mac OS默认使用UTF-8。因此,在您的情况下,文件名已正确存储,但是Linux归档程序无法理解它。


但是当我在Linux中创建zip(右键单击并压缩)时,它会创建包含“??”的条目名称的归档文件,但是当我提取它时,名称是正确的。 - hudi
当然可以,因为它使用相同的编码方式。 - Nickolay Olshevsky
我的系统代码页是UTF-8,当我使用Apache Common Archive并将编码设置为UTF-8时,它仍然无法工作。 - hudi
最简单的方法是使用十六进制编辑器/查看器检查您的存档。Windows zip 存档代码页取决于您的语言环境,对于俄语而言,它是 CP-866,对于其他语言,应该是类似于 CP-8xx 的东西。 - Nickolay Olshevsky

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接