3

私の問題は次のとおりです。テキスト ノードに UTF-8 バージョンの開始二重引用符と終了二重引用符が部分的に含まれている XML ファイルを読み込んでいます。テキストが抽出され、3999 バイトに短縮され、新しい XML 形式に変換され、ファイルとして保存されます。

入力ファイルの Notepad++ では両方の記号が正しく表示されますが、出力ファイルには無効な utf-8 文字が含まれており、Notepad++ でさえ表示できません。

開始の二重引用符は正しく出力されますが、終了の二重引用符は正しく表示されません。

Hex-Editor を使用して、コード単位が何らかの形で変更されていることがわかりました。

E2 80 9D

入力ファイルで

E2 80 3F

出力ファイルで。xml 解析に sax-parser を使用しています。

このような動作を引き起こす既知のバグはありますか?

4

3 に答える 3

1

既知のバグではありませんが、ファイルの読み取りまたは書き込み時にエンコーディングを省略するというよくある間違い - この場合は Windows-1252 であるプラットフォームの既定のエンコーディングが使用されます。

最初にファイルを読み取るときは UTF-8 デコードを指定する必要があり、新しいファイルに書き込むときは UTF-8 エンコードを指定する必要があります。実装を投稿すると、その場で修正できます。

これを再現する方法:

byte[] quoteutf8 = {(byte)0xE2, (byte)0x80, (byte)0x9D};
String decodedPlatformDefault = new String(quoteutf8, "Windows-1252");
byte[] encodedPlatformDefault = decodedPlatformDefault.getBytes("Windows-1252");

for( byte i : encodedPlatformDefault ) {
    System.out.print(String.format( "%02x ", i ));
   //e2 80 3f   
}
于 2013-01-17T12:50:25.297 に答える
1

E2 80 9D は UTF-8 の有効なバイト シーケンスであり、'”' = \u201d'. すべての上位ビットが設定されているため、これを見ることができます。これは UTF の称賛に値する安全特性であるため、「/」のようなシーケンスで ASCII が誤って検出されることはありません。

2 番目のシーケンスの 3F ('?') には、バイトに上位ビットが設定されていないため、間違っています。これは、読み取りが間違っていたことを意味します (クエスチョン マーク)。2 回変換して置き換えるようなものです。特に 9D は拡張 Windows Latin-1 aka Cp1252 (80 - 9F) にあります。

于 2013-01-17T12:47:57.560 に答える
0

バイト配列から新しい文字列を作成するとき、および文字列からバイト配列を返すときは、常に文字セット名を指定する必要があります。

そうでない場合、システムのデフォルトの文字セットが使用され、あらゆる場所で問題が発生する可能性があります...

それ以外の

new String(myByteArray);
//... and...
myString.getBytes();

あなたが使用する必要があります

new String(myByteArray, "UTF-8");
//... and...
myString.getBytes("UTF-8");

例えば

Transformer transformer = TransformerFactory.newInstance().newTransformer();

transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");

StreamResult result = new StreamResult(new StringWriter());
DOMSource source = new DOMSource(xmlDocument);
transformer.transform(source, result);

return result.getWriter().toString().getBytes("UTF-8");

Java 1.6 以降、文字セット名を含む String の代わりにCharset を指定できます。

于 2013-01-17T13:14:47.280 に答える