- ベストアンサー
JavaのStringクラスと外字について
- JavaのStringクラスには「外字」という概念は存在するのか疑問に思っています。Shift-JISの文字列データには外字が含まれているのですが、Unicodeへの変換とShift-JISへの戻しにおいて外字はどのように処理されるのでしょうか。
- JavaでShift-JISの文字列データを扱う際、文字列はUnicodeに変換されますが、外字の部分はどのように処理されるのか気になっています。また、UnicodeからShift-JISに戻す際にも外字は正しく復元されるのか不安です。
- JavaでShift-JISの文字列データに外字が含まれている場合、そのUnicodeへの変換とShift-JISへの復元はちゃんと行われるのか心配です。Stringクラスのリファレンスで「外字」について検索したが見つからず、不安になっています。
- みんなの回答 (2)
- 専門家の回答
質問者が選んだベストアンサー
#1です。 似たような質問があがっているところを見つけました。 http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?forum=12&topic=22555 ということで、これを参考に実験です。 UTF-16の外字の領域を一文字ずつShift-JISに変換して、また、UTF-16に戻して、ちゃんともとにもどるか、やってみました。 public class Gaiji { public static void main(String[] args) throws Exception { final String charSet = "Shift-JIS"; boolean allEqual = true; for (char c = 0xE000; c <= 0xF8FF; c++) { System.out.print(Integer.toHexString((int)c) + "→"); char[] carray = {c}; String source = new String(carray); byte[] sjis = source.getBytes(charSet); for (byte b : sjis) System.out.print(Integer.toHexString(((int)b & 0xFF))); System.out.print("→"); String result = new String(sjis, charSet); System.out.print(Integer.toHexString((int)result.charAt(0)) + " : "); boolean equal = source.equals(result); System.out.println(equal); allEqual = (allEqual && equal); } System.out.println(); System.out.println("すべて一致 : " + Boolean.toString(allEqual)); } } (コンパイルするときは全角スペースを半角スペースに変換してからにしてください) ところがぜんぜんダメ。 元に戻りません。 ということで、Windowsの本来の文字コードWindows-31Jでやってみました。 final String charSet = "Windows-31J"; ←変更 どうやらうまく行っているのですが、途中までは順調に変換され、元に戻るものの、途中からだめになりました。 どうやら、UTF-16 : E757 Shift-JIS : F9FC の次からだめになっています。 外字エディタで見てみるとちょうどF9FCまでが、Shift-JISの外字領域のようです。 つまり、UTF-16のほうがShift-JISより、外字領域が大きいみたいです。 当然そこから先は、Shift-JISには、変換不能ということになります。 というわけで、 1.Windowsでは、通常ならCharSetがShift-JISでも大体大丈夫だけど、外字の変換をするときにはちゃんとWindows-31Jを指定しないとダメ。 2.UTF-16 : E000~E757 Shift-JIS : F040~F9FC の範囲なら変換可能。 UTF-16 : E758~F8FF の範囲はShift-JISに相手がいないので無理。 ってことで、Shift-JISで外字が設定されているのなら、大丈夫ってことになるんじゃないでしょうか。
その他の回答 (1)
- PecoPlus
- ベストアンサー率76% (144/188)
こんばんは、興味があったので実験してみました。 (環境 WindowsXP SP2 : JDK 1.5.0_04) 外字エディタにて シフトJISで F040 Unicodeで E000 に外字を作成。(手書きのふにゃふにゃ温泉マーク) char[] c = {0xE000}; String s = new String(c); System.out.println(s); これで、ちゃんと外字が出てきました。 次に、メモ帳にて外字の温泉マークが書いてあるテキストをシフトJISで保存。 BufferedReader br = new BufferedReader(new FileReader("gaiji.txt")); for (String line; (line = br.readLine()) != null;) { System.out.println(line); } やっぱり、普通に温泉マークが出てきました。 今度は、外字エディタで作った温泉マークを削除。 さっきのコードを実行すると、温泉マークが出てこず、空白になります。 早い話が、char型変数やStringクラスが扱っているのは文字コードという純然たる数字であって、実際にフォントとして描くのはシステムに依存しているって事なんじゃないでしょうか。 つまり、結局のところ、OSでその文字コードに外字が割り当ててあれば、ちゃんと表示され、されていなければ、それなりになるって事だと思います。
補足
ありがとうございます。 これは ・Shift-JISでは外字領域はF040以降(←これは知ってました) ・UnicodeではE000以降 ・それらは1対1で対応している ・たとえばF040<->E000、F041<->E001、というように ・これをやってくれるのは、Javaの仕様 っていうことなんでしょうか。 Unicodeに直した後は、画面には表示する予定はないので、フォントの割り当てなどは気にならないのですが、Shift-JIS変換の際に相互の可逆性があるかどうかが気になっているのです。 ご存じでしたら教えてください。お願いします。<(_ _)>
お礼
ありがとうございます! 概念としても理解できましたし、扱うためのコーディング例までわかりました。本当にありがとうございました。