我正在尝试解压缩其中包含德语字符的文件夹,例如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
答案 0 :(得分:0)
您没有提及您的操作系统,也没有提及您如何创建zip文件,但是无论如何,我还是设法在Windows 10上使用 7-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 参数,如链接注释中所述:
在添加到存档对话框中,在参数字段中指定 cu :
已将压缩的文件名以UTF-8格式存储,然后可以在代码中将Charset.forName("Cp437")
替换为Charset.forName("UTF-8")
,并且解压缩时不会引发异常。
此答案特定于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>