用解决方案更新,见底部
要求:
在 Java SE 6 中处理包含文件名中带有特殊字符的文件的 ZIP 文件。由于(ZIP 生产者的)编码不是 UTF-8,特殊字符会被编码。因此,我想将特殊字符更正为正确的代码。
问题:
ZIP 包含一个名为abcüabc.txt
. 该条目通过处理java.util.zip.ZipEntry
,当打印出单个字符时,我看到这些字符(字节):
ü
被编码为
u
后跟
¨
问题:
所以我想知道如何将其替换u¨
为ü
或者ue
:
我已经尝试过但没有成功的方法:
name.replaceAll("u\\¨", "ue");
或
name.replaceAll("ü", "ue");
原始源代码(不工作):
InputStream is = new FileInputStream(new File("/Users/me/Desktop/test.zip"));
ZipInputStream zipStream = new ZipInputStream(is);
ZipEntry zipEntry = null;
while ((zipEntry = zipStream.getNextEntry()) != null) {
String name = zipEntry.getName(); // reading abcüabc.txt
System.out.println("pos 3: "+name.charAt(3));
System.out.println("pos 4: "+name.charAt(4));
System.out.println("is equal to ¨: "+Character.toString(name.charAt(4)).equals("¨"));
}
输出:
pos 3: u
pos 4:¨
is equal to ¨: false
关于我的环境的注意事项:
在 Mac OS X 10.6.8
Java SE 6 下生成的 Zip:Java HotSpot(TM) 64-Bit Server VM(内部版本 20.12-b01-434,混合模式)
解决方案
显然,ZIP 生产者(在我的情况下为 Mac OSX)将特殊字符转换为分解格式。所以 aü
被分解成u¨
.
在从 ZIP 中提取文件名时,我们希望将分解后的格式转换回组合格式,因此我们只需从上面的源代码中插入规范化:
InputStream is = new FileInputStream(new File("/Users/me/Desktop/test.zip"));
ZipInputStream zipStream = new ZipInputStream(is);
ZipEntry zipEntry = null;
while ((zipEntry = zipStream.getNextEntry()) != null) {
String name = zipEntry.getName(); // reading abcüabc.txt
System.out.println("pos 3: "+name.charAt(3));
System.out.println("pos 4: "+name.charAt(4));
System.out.println("contains ü: "+name.contains("ü"));
name = Normalizer.normalize(name, Form.NFC);
System.out.println("contains ü: "+name.contains("ü"));
}
输出:
pos 3: u
pos 4:¨
contains ü: false
contains ü: true