文字化けって技術屋さんにはよく通る道ですよね。
いろんなシステムで結構文字化けって放置されてるのが多々あるんですが(僕はよくそんな現場に投入される。。。)、原因は千差万別で、PHPとかJava内でわざわざ違う文字コードに変換してたり、EUCで構築したDBにシフトJISの文字列つっこんでたり、DB接続URLで指定すれば直ったり、HTMLにMETA指定してなかったり、モジュールアップロード時にASCIIモードFTPであげてやがったり、etc..
ここでよくあった、Javaにおいて全角マイナス(全角パイプとかも)が化けてしまう、全角チルダ(~)が波ダッシュ(全角チルダの波の山が逆な文字)に化けてしまう件についての解消法を記録しておきます。
上記の文字化けはおそらくシフトJIS(またはEUC)とunicodeとのマッピングの違いによって発生するのがほとんどでしょう。
Java上は文字はunicodeで保持されます。シフトJISでインプットされた文字列はunicodeに置換されて保持されます。
もちろんその際、OS上にあるシフトJIS-unicodeのマッピング情報を利用して置換するわけですが、シフトJISには複数種類あってそれぞれにマッピング情報を持っています。
もう少し詳しく言うとLinux(標準、sjis0201)とWindows(Microsoft、sjisMS)のそれぞれのシフト JISとunicodeとのマッピング情報は微妙に違うということです。
たとえば全角マイナス(-)。シフトJIS上はLinuxだろうがwindowsだろうが文字コードは「0x817C」です。
しかし、そのコードにマッピングされるunicodeは、Linuxの場合は「0x2212」、windowsの場合は「0xFF0D」になります。
こんなシステムもしあったら。
Linuxのtomcatで動いています。MS-EXCELをアップロードしてPOIかなんかで中身取得してシフトJISのtxtファイル作ってサーバ上に書き込みます。
エクセルはマイクロソフト製品なので、全角マイナスはアップロードして中身取得した時点で、0xFF0Dのunicodeに置換されます。
txtファイルを作成する時点で、Linux用のマッピングテーブルを使うので、0xFF0Dはマッピングテーブルに存在しないため「?」となり文字化けしてしまいます。
ということはどう解消すればよいのか?
txt ファイルを作成する前に、0xFF0D→0x2212に置換してあげればよいのです。
Javaだとこんな感じですかね?
char[] c = str.toCharArray();
for (int i = 0; i < c.length; i++) {
char d = c[i];
if (d == '\uff0d') c[i] = '\u2212';
}
str = new String(c);
やり方はいろいろあると思いますが、どこに上記コードを入れるか、ピンポイントな修正ではなくシステム全体を見て行いたいですね。
他にもどんな文字があるの?
シフトJISだと9文字、 EUCだと10文字あります。
こちらのサイト参考になります。
http://docs.hp.com/ja/5187-0702/ch09s05.html
文字化けって厄介ですよね。
僕はJavaでシステム構築するときはHTMLもDBもすべてUTF-8でやっちゃうのが一番だと思ってますが。全部一つの文字コード使えば文字化けなんて起こんないでしょ。
(もちろんインプット側の環境や前述の例みたいにエクセル使うとかだとコンバートしなきゃいけないところはありますが)
いろんなシステムで結構文字化けって放置されてるのが多々あるんですが(僕はよくそんな現場に投入される。。。)、原因は千差万別で、PHPとかJava内でわざわざ違う文字コードに変換してたり、EUCで構築したDBにシフトJISの文字列つっこんでたり、DB接続URLで指定すれば直ったり、HTMLにMETA指定してなかったり、モジュールアップロード時にASCIIモードFTPであげてやがったり、etc..
ここでよくあった、Javaにおいて全角マイナス(全角パイプとかも)が化けてしまう、全角チルダ(~)が波ダッシュ(全角チルダの波の山が逆な文字)に化けてしまう件についての解消法を記録しておきます。
上記の文字化けはおそらくシフトJIS(またはEUC)とunicodeとのマッピングの違いによって発生するのがほとんどでしょう。
Java上は文字はunicodeで保持されます。シフトJISでインプットされた文字列はunicodeに置換されて保持されます。
もちろんその際、OS上にあるシフトJIS-unicodeのマッピング情報を利用して置換するわけですが、シフトJISには複数種類あってそれぞれにマッピング情報を持っています。
もう少し詳しく言うとLinux(標準、sjis0201)とWindows(Microsoft、sjisMS)のそれぞれのシフト JISとunicodeとのマッピング情報は微妙に違うということです。
たとえば全角マイナス(-)。シフトJIS上はLinuxだろうがwindowsだろうが文字コードは「0x817C」です。
しかし、そのコードにマッピングされるunicodeは、Linuxの場合は「0x2212」、windowsの場合は「0xFF0D」になります。
こんなシステムもしあったら。
Linuxのtomcatで動いています。MS-EXCELをアップロードしてPOIかなんかで中身取得してシフトJISのtxtファイル作ってサーバ上に書き込みます。
エクセルはマイクロソフト製品なので、全角マイナスはアップロードして中身取得した時点で、0xFF0Dのunicodeに置換されます。
txtファイルを作成する時点で、Linux用のマッピングテーブルを使うので、0xFF0Dはマッピングテーブルに存在しないため「?」となり文字化けしてしまいます。
ということはどう解消すればよいのか?
txt ファイルを作成する前に、0xFF0D→0x2212に置換してあげればよいのです。
Javaだとこんな感じですかね?
char[] c = str.toCharArray();
for (int i = 0; i < c.length; i++) {
char d = c[i];
if (d == '\uff0d') c[i] = '\u2212';
}
str = new String(c);
やり方はいろいろあると思いますが、どこに上記コードを入れるか、ピンポイントな修正ではなくシステム全体を見て行いたいですね。
他にもどんな文字があるの?
シフトJISだと9文字、 EUCだと10文字あります。
こちらのサイト参考になります。
http://docs.hp.com/ja/5187-0702/ch09s05.html
文字化けって厄介ですよね。
僕はJavaでシステム構築するときはHTMLもDBもすべてUTF-8でやっちゃうのが一番だと思ってますが。全部一つの文字コード使えば文字化けなんて起こんないでしょ。
(もちろんインプット側の環境や前述の例みたいにエクセル使うとかだとコンバートしなきゃいけないところはありますが)