1

私は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クラスで機能する可能性のあるものを見つけようとしましたが、何も機能しないようです。

4

3 に答える 3

4

問題は、FileReader以前に提案されたコメンターとしてのFileInputStreamの代わりに、を使用してファイルを読み取ることです。このgo方法では、を取り出して。FileReaderに置き換えFileInputStreamます。

public void go() {
    try {
        XMLReader reader = getXMLReader();
        reader.parse(new InputSource(new FileInputStream(new File(FILE))));
    } catch (Exception ex) {
        throw new RuntimeException("The most epic fail.", ex);
    }
}

現在の方法でFileReaderは、デフォルトのプラットフォームエンコーディングを使用して、文字をSAXパーサーに渡す前にデコードしますが、これは必要なことではありません。に置き換えるとFileInputStream、XMLパーサー文字セットエンコーディングを使用して処理命令を正しく読み取り、文字セットのデコードを処理する必要があります。

FileReaderがデコードを行っているため、無効な文字が表示されています。SAXパーサーに処理させると、問題なく処理されるはずです。

于 2012-05-04T14:53:28.053 に答える
0

あなたは濁った海で釣りをしています。多くのことが誤解を招きます。@JBNizetが示したように、リーダーは何らかのエンコーディングでテキストを読み取り、すでにバイトを読み取るInputStreamで変換を行っています。エンコーディングを指定しない場合、プラットフォームエンコーディングが採用されます。

    reader.parse(new InputSource(new FileInputStream(new File(FILE))));

これは、XMLの実際のエンコーディング属性に対して中立です。

Javaソースエンコーディングはエディタエンコーディングと一致する必要があります。一致しないと、文字列リテラルが正しく機能しなくなります。

System.out.printlnも誤って表現している可能性があります。

さらに、「ISO-8859-1」はWindows Latin-1、「Windows-1252」のサブセットです。特殊文字で問題が発生した場合は、「Windows-1252」を提案してください(Javaでは「Cp1252」を使用できます)。

于 2012-05-04T15:09:12.180 に答える
0

文字()メソッドの場合:

新しいStringオブジェクトを作成するときは、最初にchar[]をbyte[]に変換してから、デフォルトの「new String(char [])」ではなく、コンストラクター「new String(byte []、StringcharSetName)」を呼び出します。

さらにヘルプが必要な場合は、http://www.exampledepot.com/egs/java.nio.charset/ConvertChar.htmlを試してください。

于 2012-05-04T14:50:33.210 に答える