私はJavaSAXパーサーを使用して、ISO-8859-1文字エンコードでXMLファイルを解析しようとしています。これは他の点ではうまくいきますが、äやöなどの特殊文字は私に頭痛の種を与えています。要するに、ContentHandler.characters(...)メソッドは私に奇妙な文字を与え、char配列を使用して指定されたエンコーディングで文字列を構築することさえできません。
これは、2つのファイルでの完全な最小動作例です。
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>|
したがって、「ö」は、ご想像のとおり、1バイトのf6でエンコードされます。
次に、UTF-8形式で保存されたJavaファイルを次に示します。
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'
(öは「ボックス内の?」に置き換えられます)、アサーションエラーが原因でクラッシュします。char配列を調べると、文字öをエンコードするcharが3バイトで構成されていることがわかります。UTF-8ではöを2バイトでエンコードする必要があるため、これらは私には意味がありません。
私が試したこと
文字配列を文字列に変換してから、その文字列のバイトを取得して、charsetエンコーディングパラメータを使用して別の文字列コンストラクタに渡すことを試みました。また、CharBuffersで遊んで、この問題を解決するためにLocaleクラスで機能する可能性のあるものを見つけようとしましたが、何も機能しないようです。