プログラマ的京都生活

2007年11月15日

[]文字符号化方式

encodingの話。@ITの記事はわかりやすくてよかった。

http://www.atmarkit.co.jp/fjava/rensai3/eclipsejava2_06/eclipse2_06_1.html


この記事読んでたら他のencodingもちょっと見てみたくなったので簡単なプログラムを作成。

private static NumberFormat nf = new DecimalFormat("000");
	
public static void main(String[] args) throws UnsupportedEncodingException {

	List<String> encodingList = new ArrayList<String>();
	encodingList.add("US-ASCII");
	encodingList.add("8859_1");
	encodingList.add("Windows-31J");
	encodingList.add("UTF-8");
	encodingList.add("ISO-2022-JP");

	printBytes("A", encodingList);
	System.out.println("-----------------------");
	printBytes("あ", encodingList);

}

private static void printBytes(String string, List<String> encodingList)
		throws UnsupportedEncodingException {

	for (String encoding : encodingList) {
		System.out.printf("%s : \t", encoding);
		byte[] bytes = string.getBytes(encoding);
		for (byte b : bytes) {
		         System.out.printf("%s ", nf.format(0x000000FF & b));
		}
	         System.out.println();
	}

}

結果

US-ASCII : 	065 
8859_1 :   	065 
Windows-31J : 	065 
UTF-8 : 	         065 
ISO-2022-JP : 	065 
-----------------------
US-ASCII : 	063 
8859_1 :  	063 
Windows-31J : 	130 160 
UTF-8 :   	227 129 130 
ISO-2022-JP : 	027 036 066 036 034 027 040 066 

「A」は全部同じバイト列だけど、「あ」はそれぞれで異なることが一目瞭然(「US-ASCII」と「8859_1」はマッピングできずに「?」をさしているので同じに見える)。

Windows-31Jだと2バイト、UTF-8だと3バイト要しているってのもすぐ分かる。ま、このように符号化方式によって違うからこそ日本語とかの文字は文字化けが起きるんだ、ってな話を新人君にしてあげたのでありました。

[]ファイルダウンロード

ファイルダウンロードプログラムを組んでいると、ファイル名の文字化けが起こるので、「ファイルダウンロード時に文字化けしないようにする方法は?」ってのはよくある質問。誰もが一度ははまる。

で、回答はこんな感じ。

fileName= new String(fileName.getBytes("Shift_JIS"), "8859_1");

最初これは何をしているのかさっぱりわからんかった。ファイル名をShiftJISエンコードしたバイト列を、ISO8859_1で文字列を作成している。当然化け化け。だってISO8859_1はASCIIをちょっと拡張した程度のもんで、日本語なんか扱えないもの。けどこれで確かにIEでは文字化けせずに動作する。

それは、どうもIEが8859_1 → ShiftJIS(Windows-31Jかも)と変換してるっぽい。「ぽい」、と書いたのはpublicなドキュメントを見つけられなかったので。もしかしたらtomcatのせい!?とも思ったけど、ネット見てたらIEではいけたけどNNではダメ、とかもあるのでやはりブラウザの内部仕様だと思われる。

実際こんなプログラムを組むと確かに復元できる。

String name = "あああ.txt";
String convertName = new String(name.getBytes("Shift_JIS"), "8859_1");
System.out.println(new String(convertName.getBytes("8859_1"), "Shift_JIS"));

Vistaちゃん

でもね、Vistaちゃんはどうするの??Vistaで追加されたJIS2004Shift_JISでは変換できませんよーっと。

そもそも、Vistaで追加された文字をファイル名に使っているファイルを、サーバーにUPして、それをXPからエクスプローラーごしに見ると「□」に化けている・・・

当然フォントはちゃんと追加してます!事実、htmlvista追加文字を含んだ文字がちゃんと表示されるし。

なんかファイル名だけ変な扱いだなぁ。


追記(2007/12/1)

そもそも、Vistaで追加された文字をファイル名に使っているファイルを、サーバーにUPして、それをXPからエクスプローラーごしに見ると「□」に化けている・・・

これ、原因はクラシックスタイルを採用していることでした。XPスタイルに戻すと普通に見えました。どういう理屈かはさっぱりわかりません。

Connection: close