home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

Java/文字コードメモ2

Java/文字コードメモ2

Java / 文字コードメモ2
id: 90 所有者: msakamoto-sf    作成日: 2006-03-14 13:44:36
カテゴリ: Java 

Shift_JIS, MS932, Windows-31J の取り扱いについて実験する。

これらは特にサーバーサイドのJavaを扱う上で何かと文字化けの原因として取りざたされている。今回示す例では、日本語の自然文で普通に使用される '' ~ '' が簡単に文字化けしてしまっている。
特にややこしいのが"Shift_JIS"と"MS932"(CP932)系の違いである。
Windows上でのShift_JISは、正確にはShift_JISをベースとして空いている外字領域にNECやIBM由来の特殊な文字を配置したエンコーディングであり、これが "CodePage932", CP932ともMS932とも、Windows-31JともMS-Kanjiとも呼ばれているエンコーディングである。

今回の記事で例示している中で、「~」「・」は本来のShift_JISに配置されているため、これだけならコンパイル時にソースファイルのエンコーディングを「Shift_JIS」と指定してもWarningは出ない。(Warningは出ないが、実際に実行してみると文字化けする。この原因は後述。)
「㈱」が混じると、こちらはCP932で13区74点、つまり本来Shift_JISには無い外字領域に配置された文字になるため、"Shift_JIS"を指定すると文字がマップできないとWarningが出力される。

"~"や"㈱"が混じったJavaソースを用意する。

public class EncodingW31 {
    public static void main(String[] args) {
        System.out.println("Windows-31J ~・㈱");
    }
}

コンパイルし、実行してみる。

ケース1:Shift_JISとしてコンパイル・実行

画像/Java/java_charactercode_2_1.jpg

上図に示すとおり、見事に文字化けしている。下はclassファイルをUTF-8対応のエディタで文字コード自動認識で開いた図。

画像/Java/java_charactercode_2_2.jpg

ケース2:MS932、あるいはWindows-31Jとしてコンパイル・実行

画像/Java/java_charactercode_2_3.jpg

上図の通り、文字化けせずに表示できた。なお、エディタで開いてみると先と同じく、自動認識ではSJISと判定されてしまった。

なお、こちらの例では"MS932"としていしてコンパイルしたが、 "Windows-31J"を指定しても同じクラスファイルが生成された。 (MD5チェックサムが同一)

結論

サーバーサイドで入力される文字コードがSJISが想定された場合は、"Shift_JIS"で受け取るのではなく"Windows-31J"あるいは"MS932"として受け取るべきである。

日本語版Windowsにより生成されたCP932の文字列を受け取ることが想定される場合は、"Shift_JIS"で受け取るのではなく"Windows-31J"あるいは"MS932"として受け取るとよいだろう。
Webアプリケーションの場合で、入力フォームがUTF-8やEUC-JPの文字コードで構成される場合は、クライアント=Webブラウザが入力フォームと同じ文字コードに変換して送信すると予想されるため、"UTF-8"や"EUC-JP"で受け取るとよいだろう。

補足:「㈱」無しで"Shift_JIS"でコンパイルしても文字化けする理由

「㈱」無しで "-encoding Shift_JIS" とした場合、コンパイルでこそWarningは出ないが、実際にうごかしてみるとやはり文字化けしてしまう。これは"~"(1区33点, 0x8160)のマッピングが原因である。
Javaは"~"について、Shift_JISとMS932で異なるUnicodeコードポイントにマッピングする。

  • Shift_JIS -> U+301C, WAVE DASH (UTF-8: 0xE3809C)
  • MS932 -> U+FF5E, FULLWIDTH TILDE (UTF-8: 0xEFBD9E)

これが、外部からの入力をJavaの内部に変換する場合のマッピングとなる。

そしてJavaの内部でのWAVE DASH, FULLWIDTH TILDEを外の世界にマッピングするときが問題となる。

  • U+301C(WAVE DASH) -> "MS932" 以外のみ Shift_JISの0x8160にマッピング可能
  • U+FF5E(FULLWIDTH TILDE) -> "MS932" のみ Shift_JISの0x8160にマッピング可能

Windows用のJavaVMで普通にSystem.out.println()する場合はMS932が「内→外」変換として使われる(PrintStreamの文字列出力は、プラットフォームのデフォルトの文字エンコーディングを使ってバイトに変換される)。
従って、"-encodign Shift_JIS"でコンパイルしたclassファイル中の「~」(U+301C WAVE DASH)はMS932ではマップされないため、"?"として文字化けすることになる。

参考(Windows-31JとJava関連)

参考 ("~"での文字化け, JavaでのUnicodeのマッピング問題など)



プレーンテキスト形式でダウンロード
現在のバージョン : 3
更新者: msakamoto-sf
更新日: 2015-02-08 00:11:31
md5:2b4232deb271a6de2dd430f119270174
sha1:c5bf27f36fbdbc5487e275fd76ae8bc8e233081e
コメント
コメントを投稿するにはログインして下さい。