2014年11月26日水曜日

Javaの文字コード変換サンプルコード2

java.nio.charset.Charsetにあるdecodeとencodeの挙動が気になったのでサンプルを書いてみた。

まず、仕様の簡単な説明。

Charset.encodeは、入力としてStringを受け取り、出力として任意の文字コードのバイト列を出力する。

Charset.decodeは、入力として、UTF-8とかShift-JISでエンコードされた文字のバイト列を与えると、出力としてUnicode(UTF-16)で変換された文字のバイト列が出力される。

文字コードの指定は下記のようにCharsetのインスタンスを取得する過程で行う。

Charset cs = Charset.forName("Shift-JIS")
cs.encode(new String("エンコードしたい文字")); 

次に、サンプルコードを書いて、encode/decodeした時にどのようなバイト列が格納されているのか確認してみた。


public static void sampleEncoder(String target,Charset cs){
 /** まずは元のStringデータをCharに分解して確認してみる**/
 System.out.print("Original: ");
 char[] chars = new char[target.length()];
 target.getChars(0,target.length(),chars,0);
 for(int i = 0; i < chars.length; i++){
  System.out.print((int)chars[i] + " ");
 }
 System.out.println();

 /** 次にStringを指定されたEncodeに変換し、バイト表現を確認する **/
 ByteBuffer bf = cs.encode(target);
 System.out.print(cs.toString() + ": ");
 for(int i = 0 ; i < bf.array().length; i++) {
  System.out.print((int)bf.array()[i] + " ");
 }
 System.out.println();
 /** 最後にEncodeした文字を、同じ文字コードで再びDecodeし、Charとしての表現を確認する **/

 CharBuffer cb = null;
 cb = cs.decode(bf);

 StringBuffer sb = new StringBuffer();
 System.out.print("Unicode(UTF-16): ");

 for(int i = 0 ; i < cb.array().length; i++) {
  System.out.print((int)cb.array()[i] + " ");
  sb.append(cb.array()[i]);
 }

 System.out.println(" :" + sb.toString());
 System.out.println();
}
public static void main(String args[]){
 sampleEncoder("日本語",Charset.forName("ISO-2022-JP"));
 sampleEncoder("日本語",Charset.forName("Shift-JIS"));
 sampleEncoder("日本語",Charset.forName("EUC-JP"));
}
これの実行結果は次のようになる。

Original: 26085 26412 35486 
ISO-2022-JP: 27 36 66 70 124 75 92 56 108 27 40 66 
Unicode(UTF-16): 26085 26412 35486 0 0 0  :日本語


Original: 26085 26412 35486 
Shift_JIS: -109 -6 -106 123 -116 -22 
Unicode(UTF-16): 26085 26412 35486  :日本語

Original: 26085 26412 35486 
EUC-JP: -58 -4 -53 -36 -72 -20 0 0 0 
Unicode(UTF-16): 26085 26412 35486  :日本語


見方を少し説明すると、Originalと書いてある行には、"日本語"を代入したStringのchar表現が出力されている。
次の行はそれぞれの文字コードでエンコードした結果のバイト列表現。
そして、3行目にはエンコードした結果を再度デコードし、一行目の値と同じか確認をしている。

出力結果を見ると、encodeした結果はそれぞれ違うバイト表現が入っているので、おそらくその文字コードでエンコードされた結果が入っていることが確認できる。そして、それらをdecodeした結果は再度String型の時と同じ表現に戻っているようだ。

ISO-2022-JPの時には、最後に0,0,0と他にはないバイトが入っているが。これはなぜだろうか。。
標準出力自体は"日本語"と正しく出力できているようだが。

0 件のコメント:

コメントを投稿