2009-08-13 21 views
5

JavaでUTF-8文字列の一部をデコードしようとしています。 これらの文字列には、CC 88(合成ジアレシス)など、いくつかの結合ユニコード文字が含まれています。 文字列はOKであるようです。http://www.fileformat.info/info/unicode/char/0308/index.htmJava UTF-8の異常な動作

ただし、文字列への変換後の出力は無効です。

byte[] utf8 = { 105, -52, -120 }; 
System.out.print("{{"); 
for(int i = 0; i < utf8.length; ++i) 
{ 
    int value = utf8[i] & 0xFF; 
    System.out.print(Integer.toHexString(value)); 
} 
System.out.println("}}"); 
System.out.println(">" + new String(utf8, "UTF-8")); 

出力:

 
    {{69cc88}} 
    >i? 

答えて

9

あなたが(例えばウィンドウ)に出力しているコンソールがUnicodeをサポートしていない可能性、および文字をマングルことがあります。コンソールの出力はデータを正しく表していません。

出力をファイルに書き込む代わりに、FileWriterでエンコードが正しいことを確認してから、ファイルをユニコード対応のエディタで開きます。

また、デバッガを使用して文字が期待通りであることを確認してください。ただコンソールを信用しないでください。

+0

+1:端末(gnome-terminal)のUbuntu 9.04では、おそらくそれを期待して出力にiがあります。 –

+0

私はこの単語「分音符」が好きです。私は会話でもっと頻繁に使用しなければならないかもしれません。 – skaffman

+1

:) 「ウムラウト」も試してみてください。あなたは夕方の男になるでしょう。 –

4

コードは問題ありませんが、skaffmanはコンソールが適切な文字をサポートしていない可能性があると述べています。確かにテストする

、あなたは文字のUnicode値をプリントアウトする必要があります: - correct(U + 0069、U + 0308)である

public class Test { 
    public static void main(String[] args) throws Exception { 
     byte[] utf8 = { 105, -52, -120 }; 
     String text = new String(utf8, "UTF-8"); 
     for (int i=0; i < text.length(); i++) { 
      System.out.println(Integer.toHexString(text.charAt(i))); 
     } 
    } 
} 

これは69、308を印刷します。

4

どちらも正しいです。ありがとう!!

私は最終的にWindows上のEclipseで、問題を解決する方法ここで

:実行構成、引数]タブで

  • を、私は実行コンフィギュレーションでVM引数
  • に「-Dfile.encoding=UTF-8」を追加、共通のタブ、私はUTF-8

にコンソールエンコーディングを設定し、私は次のようにコードを変更:

byte[] utf8 = { 105, -52, -120 }; 
System.out.print("{{"); 
for(int i = 0; i < utf8.length; ++i) 
{ 
    int value = utf8[i] & 0xFF; 
    System.out.print(Integer.toHexString(value)); 
} 
System.out.println("}}"); 

PrintStream sysout = new PrintStream(System.out, true, "UTF-8"); 
sysout.print(">" + new String(utf8, "UTF-8")); 

出力:

 
{{69cc88}} 
> ï 

ありがとう!

+0

PrintStreamを使用してデータを自分でエンコードする場合は、 "-Dfile.encoding = UTF-8"スイッチは必要ありません。 ( "file.encoding"プロパティを手動で設定することは、システムのエンコーディングを知る必要があるすべてのコードで問題になる可能性があります。) – McDowell

1

Javaは、ユニコード文字をネイティブシステムでエンコードされたバイトに符号化してから、stdoutに書き込みます。いくつかのオペレーティングシステムは、多くのLinuxディストリビューションと同様に、デフォルトの文字セットとしてUTF-8を使用しています。

さまざまな下位互換性の理由から、Windowsでは少し違っています。デフォルトのシステムエンコーディングは "ANSI"のコードページの1つになります。デフォルトのコマンドプロンプト(cmd.exe)を開くと、古い "OEM"のDOSコードページの1つになります(ただし、ANSIとUnicodeを取得することは可能です)with a bit of work )。

U + 0308は "ANSI"文字セット(おそらく1252)に含まれていないため、エラー文字(通常は疑問符)としてエンコードされます。

Unicodeの有効化すべての代替は、組み合わせのシーケンスUは+単一文字U + 00EFに0069 U + 0308 normalizeにある:

public static void emit(String foo) throws IOException { 
    System.out.println("Literal: " + foo); 
    System.out.print("Hex: "); 
    for (char ch : foo.toCharArray()) { 
     System.out.print(Integer.toHexString(ch & 0xFFFF) + " "); 
    } 
    System.out.println(); 
    } 

    public static void main(String[] args) throws IOException { 
    String foo = "\u0069\u0308"; 
    emit(foo); 
    foo = Normalizer.normalize(foo, Normalizer.Form.NFC); 
    emit(foo); 
    } 

windows-1252の下では、このコードが出力されます:

 
Literal: i? 
Hex: 69 308 
Literal: ï 
Hex: ef 
関連する問題