java.lang.String#getBytes() の動作仕様
Unicode から Shift_JIS(CP932) に変換するときの java.lang.Stringクラス getBytesメソッドの動作仕様について。
例として、"♨ B" のUTF-8のバイト列を Shift_JIS(CP932) のバイト列に変換する処理を Java コードで示す。
public class Main { public static void main(String[] args) { try { byte[] utf8_byte_array = { (byte)0xe2, (byte)0x99, (byte)0xa8, (byte)0x20, (byte)0x42 }; // "♨ B" のUTF-8のバイト列 String str = new String(utf8_byte_array, "UTF-8"); // UTF-8 のバイト列を String オブジェクトに変換 byte[] sjis_byte_array = str.getBytes("MS932"); // String オブジェクトを Shift_JIS(CP932) のバイト列に変換 System.out.println(str); // String オブジェクトを表示 printByteArray(utf8_byte_array); // UTF-8 のバイト列を16進数で表示 printByteArray(sjis_byte_array); // Shift_JIS(CP932) のバイト列を16進数で表示 } catch (Exception e) { // do nothing } } private static void printByteArray(byte[] byte_array) { for (int i=0; i<byte_array.length; i++) { System.out.print( String.format("%02x ", byte_array[i]) ); } System.out.println(); } }
コンパイルする
$ javac Main.java
実行結果は下記となる。
$ java Main ♨ B e2 99 a8 20 42 3f 20 42
「♨」 という文字は Unicode のコードポイント U+2668 に定義されるが、Shift_JIS(CP932) の文字集合には存在しないため代替文字「?」(16進数の3f)に置換されている。
疑問
デフォルトの代替文字「?」を別の文字にすることは可能か?
できそう。
String#getBytes()やnew String()は、内部ではCharsetDecoderやCharsetEncoderクラスが使われている。これらを直接使えば、変換できない文字コードを「?」にせずにエラーにする、といった処理を実装できる。