2012-01-31 8 views
1

私はJavaを使い慣れていません。私はUnicodeに関連していると思ういくつかの問題があります。Java Unicodeの問題(私だと思います)

私はScannerを使用して、UTF-8エンコーディングで保存されたテキストファイルからトークン化されたコマンドを読み込みました。基本的には、コマンドが "command1"または "command2"(これらの場合は何か他のことをしている)と等しくないことを最初に確認し、それ以外の場合は文字を読み込みます。トークンが1文字でない場合は、エラーを出力します。ここで

は私のコードです:

public static void main(String[] args) throws FileNotFoundException { 
    Scanner scanner = new Scanner(new File(args[0])); 
    while (scanner.hasNext()) { 
     String command = scanner.next(); 
     if (command.equals("command1")) { 
      System.out.println("command: command1"); 
      // do something 
     } else if (command.equals("command2")) { 
      System.out.println("command: command2"); 
      // do something 
     } else { 
      if (command.length() == 1) { 
       char c = command.charAt(0); 
       System.out.println("character: " + c); 
       // do something with c 
      } else { 
       System.err.println("error (string was " + command 
         + " with length " + command.length() + ")"); 
      } 
     } 
    } 
} 

とファイル名、私はテストのために[0]引数に渡しているテキストファイルの内容:

command1 
x 
y 
command2 
z 
└ 
command1 
╒ 
═ 

期待出力は次のとおりです。

command: command1 
character: x 
character: y 
command: command2 
character: z 
character: └ 
command: command1 
character: ╒ 
character: ═ 

実際の出力は:

です。
command: command1 
character: x 
character: y 
command: command2 
character: z 
error (string was └ with length 3) 
command: command1 
error (string was ╒ with length 3) 
error (string was ═ with length 3) 

ご覧のとおり、非標準文字はJavaによって3文字の文字列として認識されています。不思議なことに、端末出力の文字の1つをSystem.out.println("└".length())ステートメントにコピー/ペーストすると、正しく1が印刷されます。

どこが間違っているのでしょうか?
ありがとう

+0

"トークンが1文字でない場合は、エラーを出力します。" 'String'の' length() 'メソッドは、文字数ではなく、UTF-16コード単位の数を返します。これらはしばしば同じではありません。 – bames53

+0

@ bames53それを指摘してくれてありがとう。 Stringが単一の文字であるかどうかをテストする良い方法がありますか、これはちょっとしたことに気を付けるだけの可能性がありますか? – chigley

+0

「シングルキャラクター」の意味によって異なります。コード・ポイントが文字であるというユース・ケースの合理的な定義であれば、サロゲート・ペアを監視する必要があります。文字を組み合わせるようなことを可能にする定義が必要な場合は、おそらくUnicodeのプロパティやその他のものについてすべて知っているライブラリが必要になるでしょう。 - Unicodeテキストの扱いは複雑です。正直なところ、そこにあるソフトウェアの多くは間違っているが、それでも有用である。だからあなたはそれについて少し勉強したいかもしれませんが、実装する努力の価値がないと決めるかもしれません。 – bames53

答えて

8

Javaでファイルを開くと、エンコーディング(指定しない場合)はfile.encodingシステムプロパティから取得されます。これはあなたが欲しいものに設定されることはほとんどありません(あなたが私のようなものなら、あなたは常にUTF-8が必要です)。修正するには

あなたのスキャナを作成するときに、明示的に文字セットを指定:

Scanner scanner = new Scanner(new File(args[0]), "UTF-8"); 
+0

華麗な、ありがとう! – chigley

0

を私はあなたの問題はエンコードの不一致から実際に来てみています。 スキャナのコンストラクタで文字セットを渡そうとしましたか?

私のシステム(Arch Linux 64b、Java 6.0.30)では、あなたのコードはUTF-8でデフォルトのロケールで完全に動作します。 Windowsを実行している場合、ロケールはWin-CP1252で、スキャナで使用できます。

関連する問題