1

用解决方案更新,见底部

要求
在 Java SE 6 中处理包含文件名中带有特殊字符的文件的 ZIP 文件。由于(ZIP 生产者的)编码不是 UTF-8,特殊字符会被编码。因此,我想将特殊字符更正为正确的代码。

问题
ZIP 包含一个名为abcüabc.txt. 该条目通过处理java.util.zip.ZipEntry,当打印出单个字符时,我看到这些字符(字节):

ü被编码为
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ü被分解成.
在从 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
4

2 回答 2

3

那不是¨U+00A8 DIAERESIS),而是U+0308 COMBINING DIAERESIS

字符是这样拆分的,因为 Mac Os 将文件名存储在规范化表单 D 中,它像这样分解字符。

你可以像这样组合它:

String name = zipEntry.getName(); 
name = Normalizer.normalize(name, Form.NFC);

有关规范化表格的更多信息

分音符之间的区别在于它们如何修改或不修改前一个基本字符:

    System.out.println( "u" + (char)0xA8); //u¨
    System.out.println( "u" + (char)0x0308); //ü
于 2013-01-07T13:04:01.803 回答
0

您可以使用apache ant解决编码问题。

进口org.apache.tools.zip.*

ZipFile zipFile = new ZipFile(fileName,"you encoding");// you encoding like utf-8 
Enumeration emu = zipFile.getEntries();


while(emu.hasMoreElements()){
  ZipEntry entry = (ZipEntry) emu.nextElement();
  // do something
}

Ant 项目不提供在线文档,这里是另一个文档http://api.dpml.net/ant/1.7.0/

于 2013-01-07T13:03:39.073 回答