我一直在尝试使用 Java SAX 解析器来解析 ISO-8859-1 字符编码的 XML 文件。否则这很好,但是像ä和ö这样的特殊字符让我很头疼。简而言之,ContentHandler.characters(...)方法给了我奇怪的字符,你甚至不能使用 char 数组来构造具有指定编码的 String。
这是两个文件中的完整最小工作示例:
latin1.xml:
<?xml version='1.0' encoding='ISO-8859-1' standalone='no' ?>
<x>Motörhead</x>
该文件以所述 Latin-1 格式保存,因此 hexdump 给出:
$ hexdump -C latin1.xml
00000000 3c 3f 78 6d 6c 20 76 65 72 73 69 6f 6e 3d 27 31 |<?xml version='1|
00000010 2e 30 27 20 65 6e 63 6f 64 69 6e 67 3d 27 49 53 |.0' encoding='IS|
00000020 4f 2d 38 38 35 39 2d 31 27 20 73 74 61 6e 64 61 |O-8859-1' standa|
00000030 6c 6f 6e 65 3d 27 6e 6f 27 20 3f 3e 0a 3c 78 3e |lone='no' ?>.<x>|
00000040 4d 6f 74 f6 72 68 65 61 64 3c 2f 78 3e |Mot.rhead</x>|
因此,正如您所期望的那样,“ö”使用单个字节 f6 进行编码。
然后,这里是 Java 文件,以 UTF-8 格式保存:
MySAXHandler.java:
import java.io.File;
import java.io.FileReader;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
public class MySAXHandler extends DefaultHandler {
private static final String FILE = "latin1.xml"; // Edit this to point to the correct file
@Override
public void characters(char[] ch, int start, int length) {
char[] dstCharArray = new char[length];
System.arraycopy(ch, start, dstCharArray, 0, length);
String strValue = new String(dstCharArray);
System.out.println("Read: '"+strValue+"'");
assert("Motörhead".equals(strValue));
}
private XMLReader getXMLReader() {
try {
SAXParser saxParser = SAXParserFactory.newInstance().newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setContentHandler(new MySAXHandler());
return xmlReader;
} catch (Exception ex) {
throw new RuntimeException("Epic fail.", ex);
}
}
public void go() {
try {
XMLReader reader = getXMLReader();
reader.parse(new InputSource(new FileReader(new File(FILE))));
} catch (Exception ex) {
throw new RuntimeException("The most epic fail.", ex);
}
}
public static void main(String[] args) {
MySAXHandler tester = new MySAXHandler();
tester.go();
}
}
运行该程序的结果是它输出Read: 'Mot�rhead'
(ö 替换为“? in a box”),然后由于断言错误而崩溃。如果您查看 char 数组,您会看到编码字母 ö 的 char 由三个字节组成。它们对我没有任何意义,因为在 UTF-8 中,ö 应该用两个字节编码。
我试过的
我尝试将字符数组转换为字符串,然后将该字符串的字节传递给另一个带有字符集编码参数的字符串构造函数。我也玩过 CharBuffers 并试图找到可能与 Locale 类一起使用的东西来解决这个问题,但我尝试的任何方法似乎都不起作用。