Murayama blog.

プログラミングと、その次の話

SHIFT_JISとWindows-31Jと、から〜(WAVE DASH)

今までわかったふりをしてきた文字コードの復習。
間違ってたらつっこんで下さい。


Eclipse上で以下のファイルを作成して実行します。

package sample;

import java.nio.charset.Charset;

public class Sample {
	public static void main(String[] args) {

		System.out.println(Charset.defaultCharset().name());

		String kara = "〜";
		System.out.printf("Unicode:%x%n", (int)kara.charAt(0));
		System.out.println(kara);
	}
}


まず実行結果を。

windows-31j
Unicode:ff5e
〜

僕の環境だとこんなかんじで表示されます。


で、こっから。
まず、ソースコードSample.javaのテキストファイルエンコーディングを確認。
Eclipse上でソースファイルを選択してプロパティを表示します。



そーするとデフォルト設定のMS932になっていることが確認できます。
MS932=Windows-31Jと同じです。


また、実行結果からわかるように
VMのデフォルトのキャラクタセットもWindows-31Jになっています。
この結果としてEclipseのコンソール出力時もWindows-31Jで出力される、ということになります。
なのでこの場合、なんてことなく実行できます。

コンソール出力時にSHIFT_JISで出力してみると

EclipseからRun Configurationsを選択し、CommonタブからConsole EncodingをSHIFT_JISに変更します。



そんで実行すると、いい具合に文字化けします。

Shift_JIS
Unicode:ff5e
?

一番下の行が?になってます。
そんで、デフォルトのキャラクタセットSHIFT_JISに変わってます。

なぜ文字化けするか?

「〜」(WAVE DASH)は、
Windows-31Jの場合とSHIFT_JISの場合とでUnicodeへのマッピングが違います。

文字 SHIFT_JIS Windows-31J
〜(WAVE DASH) U+301C U+FF5E


Sample.javaのテキストファイルエンコーディングはWindows-31Jでした。
また、さきほどの文字化けした例の実行結果を見ると、

Shift_JIS
Unicode:ff5e
?

Unicode:ff5eとなっています。
つまり、これは

		String kara = "〜";

のステートメントで、変数karaはUnicodeのU+ff5eという値を保持する、ということを意味します。
このU+ff5eのデータを、

		System.out.println(kara);

としたとき、コンソール出力時のエンコードSHIFT_JISであるため文字化けが発生します。
SHIFT_JISで「〜」文字を出力するには、U+301Cでなければならない)

SHIFT_JIS出力時に「〜」文字を出力するには

U+ff5eをU+301Cに変換してあげればOK。
コードはこんなかんじ。ちょっと雑。

package sample;

import java.nio.charset.Charset;

public class Sample {
	public static void main(String[] args) {

		System.out.println(Charset.defaultCharset().name());

		String kara = "〜";
		System.out.printf("Unicode:%x%n", (int)kara.charAt(0));

		// U+ff5eをU+301cに変換
		if(0xff5e == (int)kara.charAt(0)){
			kara = "\u301c";
		}
		System.out.println(kara);
	}
}

補足:テキストファイルエンコーディングSHIFT_JISにしてみると

実行結果は、

Shift_JIS
Unicode:301c
〜

となり、Unicode:301cとなっていることが確認できます。