Java,解压缩文件夹,文件名中带有德语字符

时间:2019-03-28 09:18:37

标签: java utf-8 unzip

我正在尝试解压缩其中包含德语字符的文件夹,例如Aufhänge。 我知道在Java 7中,默认情况下使用的是utf-8,我认为“ä”是utf-8字符之一。 这是我的代码段

public static void main(String[] args) throws IOException {
    ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(ZIP_PATH), StandardCharsets.UTF_8);
    ZipEntry zipEntry;
    while ((zipEntry = zipInputStream.getNextEntry()) != null) {
        System.out.println(zipEntry.getName());
    }
}

这是我得到的错误:java.lang.IllegalArgumentException:MALFORMED

它与Charset.forName(“ Cp437”)一起使用,但不适用于StandardCharsets.UTF_8

1 个答案:

答案 0 :(得分:0)

您没有提及您的操作系统,也没有提及您如何创建zip文件,但是无论如何,我还是设法在Windows 10上使用 7-Zip 重新创建了您的问题:

  • 创建一个包含一些琐碎内容的简单文本文件(例如,只有三个字符“ abc”)。
  • 将文件另存为 D:\ Temp \Aufhänge.txt。请注意文件名中的变音符号。
  • 在Windows文件资源管理器中找到该文件。
  • 选择文件,然后单击鼠标右键。从上下文菜单中选择 7-Zip>添加到“Aufhänge.zip” ,以创建Aufhänge.zip

然后,在NetBeans中运行以下代码以解压缩刚刚创建的文件:

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

public class GermanZip {

    static String ZIP_PATH = "D:\\Temp\\Aufhänge.zip";

    public static void main(String[] args) throws FileNotFoundException, IOException {

        ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(ZIP_PATH), Charset.forName("UTF-8"));
        ZipEntry zipEntry;
        while ((zipEntry = zipInputStream.getNextEntry()) != null) {
            System.out.println(zipEntry.getName());
        }
    }

}

正如您所指出的那样,代码在执行以下语句java.lang.IllegalArgumentException: MALFORMED时会抛出zipEntry = zipInputStream.getNextEntry()) != null

出现问题是因为默认情况下,{strong> 7压缩使用Cp437对zip文件中的文件名进行编码,如this comment from 7-Zip中所述:

  

默认编码为OEM(DOS)编码。是为了与   旧的zip软件。

这就是为什么在使用Charset.forName("Cp437")而不是Charset.forName("UTF-8")时解压缩有效的原因。

如果您想使用Charset.forName("UTF-8")解压缩,则必须强制 7-Zip 在UTF-8中对zip中的文件名进行编码。为此,请在运行 7-Zip 时指定 cu 参数,如链接注释中所述:

  • 在Windows文件资源管理器中,选择文件并右键单击。
  • 从上下文菜单中选择 7-Zip>添加到存档...”
  • 添加到存档对话框中,在参数字段中指定 cu

    AddToArchive

  • 已将压缩的文件名以UTF-8格式存储,然后可以在代码中将Charset.forName("Cp437")替换为Charset.forName("UTF-8"),并且解压缩时不会引发异常。

    < / li>

此答案特定于Windows 10和7-Zip,但一般原理应适用于任何环境:如果为ZipInputStream指定UTF-8编码,请确保zip文件中的文件名确实使用UTF-8编码。您可以通过在二进制编辑器中打开zip文件并搜索压缩文件的名称来轻松验证这一点。


根据以下OP的评论/问题进行更新:

  • 不幸的是,.ZIP File Format Specification当前没有提供一种存储压缩文件名所用编码的方法,除了一个例外,如“附录D-语言编码(EFS)”所述:

      

    D.2如果未设置通用位11,则文件名和注释   应该符合原始的ZIP字符编码。 如果一般   目的位11被设置,文件名和注释必须支持   Unicode标准版本4.1.0或更高版本,使用字符   编码格式由UTF-8存储规范定义。   Unicode标准由Unicode联盟发布   (www.unicode.org)。存储在ZIP文件中的UTF-8编码数据是   应该不包含字节顺序标记(BOM)。

  • 因此,在您的代码中,对于每个压缩文件,首先检查通用位标志的位11是否已设置。如果是,则可以确定该压缩文件的名称是使用 UTF-8 编码的。否则,编码将是创建压缩文件时使用的编码。在Windows上默认为 Cp437 ,但是如果您在Windows上运行并处理在Linux上创建的zip文件,我认为没有简单的方法可以确定所使用的编码。< / p>

  • 很遗憾,ZipEntry没有提供访问压缩文件的通用位标志字段的方法,因此您需要在字节级别处理zip文件才能做到这一点。
  • 为了进一步增加复杂性,本文中的“编码”与每个压缩文件名而不是zip文件本身使用的编码有关。可以使用 UTF-8 编码一个压缩文件名,可以使用 Cp437 等添加另一个压缩文件名。
相关问题