#経緯
Javaで作成したWEBアプリケーションにで"~"が文字化けするという不具合があった。
DBの文字コードがUTF-8、CSV出力がMS932であったため、異なる文字コードの変換による文字化けかと思って調査していたら、もっと単純な話だった。
結構時間を無駄にしたので、メモもかねて残しておく。
#原因
DBがUTF-8でも、Javaでは内部表現であるUTF16になるため、ここでは問題ない。
処理を追っていると、DBからデータ取得後、Javaの処理でSHIFT-JISに変換してからMS932に変換していた。"~"で出てくるSHIFT-JIS, MS932の変換問題かと思ったら、SHIFT-JIS、UTF16(Javaの内部表現)の変換問題だった。
#文字変換例
簡単なソースコードを作成して検証してみた。(java:1.8.0_121)
SHIFT-JISとMS932のバイト配列に変換してから、Javaの文字列を生成するとSHIFT-JISだけ文字化けが発生している。
String org = "~";
byte[] sjBytes = org.getBytes("SHIFT-JIS");
byte[] ms932Bytes = org.getBytes("MS932");
String sj = new String(sjBytes, "SHIFT-JIS");
String ms932 = new String(ms932Bytes, "MS932");
String fmt = "%s\t文字列:%s, バイト配列:%s";
System.out.println(String.format(fmt, "元の文字", org, DatatypeConverter.printHexBinary(org.getBytes())));
System.out.println(String.format(fmt, "SHIFT-JIS", sj, DatatypeConverter.printHexBinary(sjBytes)));
System.out.println(String.format(fmt, "MS932", ms932, DatatypeConverter.printHexBinary(ms932Bytes)));
#出力結果
元の文字 文字列:~, バイト配列:EFBD9E
SHIFT-JIS 文字列:?, バイト配列:3F
MS932 文字列:~, バイト配列:8160
#まとめ
そもそもUTF-8にすれば問題ないけど、仕様変更になるため扱いが厄介。
どうしてもSHIFT-JISを使いたい場合はMS932で十分なので、SHIFT-JISは使用しない。