文字コードに含まれない文字を String#getBytes() すると強制的に「3F(半角はてな[?])」に置き換わる

「郄(ハシゴ高)」(UTF-8に存在するが、Shift_JISに存在しない文字)

byte[] utf8 = "郄".getBytes("UTF-8"); // E9AB99
byte[] shiftjis = "郄".getBytes("Shift_JIS"); // 3F -> ?

System.out.println("getBytes(UTF-8):" + bytesToHexString(utf8));
System.out.println("getBytes(Shift_JIS):" + bytesToHexString(shiftjis));
System.out.println("? == getBytes(UTF-8):" + Arrays.equals("?".getBytes("UTF-8"), utf8));
System.out.println("? == getBytes(Shift_JIS):" + Arrays.equals("?".getBytes("Shift_JIS"), shiftjis));

実行結果


getBytes(UTF-8):E9AB99
getBytes(Shift_JIS):3F
? == getBytes(UTF-8):false
? == getBytes(Shift_JIS):true


これでは元々「半角はてな」であったのか
文字コードに含まれないので「半角はてな」に置き換えられたのか
区別がつかない…
ちょっと工夫しないといけないですね


ちなみに UTF-8エンコードのファイルを
BufferedReader(fileName, "Shift_JIS")#readLine()
などで読み込んでも同じことになる
内部でUTF-16で読み込んだあとでShift_JISに変換しているので当然と言えば当然か…


bytesToHexString() メソッドについてはこちら
byte(-128 ~ 127)の配列を16進数表記(00 ~ FF)に変換 - 不会忘記的一天