2004.10.17 新規作成。2004.12.19 加筆。2005.04.02加筆。
最近、コンピュータで扱う文字列の文字コードがUnicodeでなければならない場面が増えてきた。UnicodeとシフトJIS、EUC-JPを変換する機会が多い。この変換は変換表で行うが、変換表が実際的なものでなければ、文字化けが発生することになる。
おかしな変換表は、これまでは、特にLinuxなどの上で動作するオープンソースソフトウェアで多く見られた。おそらく規格原理主義者が多かったためだろう。そもそも、規格どおりに変換表を作ると、実用的な変換表にはならない。しかし、最近ではまともな変換表を実装しているものも増えてきて、うまく選ぶだけでいいようになってきている。
ソフトウェアごとの変換表とその違いをまとめたページはよく見かけるが、では実際にどのように変換するものを選べばいいか不明なので、まとめてみた。
このページでは、「文字」を単にコードポイントが与えられて一意に区別できるもの、ぐらいの意味で使う。包摂規準がどうあるべきか、あるいは本質的にコンピュータでの文字とは何であるか、などについては立ち入らない。
実際的な変換表は、できるかぎりround-trip conversionを達成し、なおかつ、異なるシステム上のソフトウェアとの情報交換を考慮したもの、ということになる。
Unicodeと、シフトJIS、EUC-JPとの妥当な変換表は、少なくても次の点を満たしていなければならない。
0x5C をU+00A5 YEN SIGN に変換してしまうと、内部Unicodeなプログラミング言語などで、この文字がバックスラッシュとして扱われない。次の表で、真ん中の列のように変換しては不味い。
| シフトJIS / EUC-JP | Unicode(誤り) | Unicode(妥当) |
|---|---|---|
| 0x7E | U+203E OVERLINE | U+007E TILDE |
| EUC-JP 0xA1C0 | U+005C REVERSE SOLIDUS | U+FF3C FULLWIDTH REVERSE SOLIDUS |
| EUC-JP 0x8FA2B7 | U+007e TILDE | U+FF5E FULLWIDTH TILDE |
IRVとJIS X 0208には同じ文字(例えばスラッシュ'/')が含まれ、またJIS X 0201とJIS X 0208にも同じ文字が含まれている(カタカナ)。本来は文字ではなく書式の話だが、現実には、JIS X 0208は全角として、JIS X 0201は半角として表示するように期待されているので、別の字として扱う必要がある。
丸囲み数字などが含まれた、既存の大量の文書を捨てるわけにはいかない。IBM拡張文字についても同じ。round-trip conversionを維持すること。
JIS X 0212補助漢字、あるいはJIS X 0213漢字集合(これはJIS X 0208と互換性がない。)は、現段階ではサポートする必要はないと思う。
ところで、NEC特殊文字にはJIS X 0208に含まれる文字があり(多重符号化)、NEC選定IBM拡張文字もIBM拡張文字と被っている。
| 文字集合 | 内容 | コードポイント |
|---|---|---|
| NEC特殊文字 | 丸囲み数字、記号など | シフトJISで0x8740〜0x879c、EUC-JPで0xADA1〜0xADFC |
| NEC選定IBM拡張文字 | 漢字、ローマ数字など | シフトJISで、0xed40〜0xeefc |
| IBM拡張文字 | 漢字、ローマ数字、(株)、No.など | シフトJISで0xfa40〜0xfc4b、EUC-JPで0x8FF3F3〜0x8FF4FE |
これらについては、プライベート領域 (Private Use Area; PUA, U+E000〜U+F8FF) などを駆使して別の文字に変換する手もあるが、他システムとの情報交換を考慮すると、round-trip conversionを放棄し、次のように変換したほうがいい。
| シフトJIS | Unicode | シフトJIS | 名称 |
|---|---|---|---|
| 0x8790 | -> U+2252 | -> 0x81e0 | APPROXIMATELY EQUAL TO OR THE IMAGE OF |
| 0x8791 | -> U+2261 | -> 0x81df | IDENTICAL TO |
| 0x8792 | -> U+222b | -> 0x81e7 | INTEGRAL |
| 0x8795 | -> U+221a | -> 0x81e3 | SQUARE ROOT |
| 0x8796 | -> U+22a5 | -> 0x81db | UP TACK |
| 0x8797 | -> U+2220 | -> 0x81da | ANGLE |
| 0x879a | -> U+2235 | -> 0x81e6 | BECAUSE |
| 0x879b | -> U+2229 | -> 0x81bf | INTERSECTION |
| 0x879c | -> U+222a | -> 0x81be | UNION |
| シフトJIS | Unicode | シフトJIS | 名称 |
|---|---|---|---|
| 0xfa4a | -> U+2160 | -> 0x8754 | ROMAN NUMERAL ONE |
| 0xfa4b | -> U+2161 | -> 0x8755 | ROMAN NUMERAL TWO |
| 0xfa4c | -> U+2162 | -> 0x8756 | ROMAN NUMERAL THREE |
| 0xfa4d | -> U+2163 | -> 0x8757 | ROMAN NUMERAL FOUR |
| 0xfa4e | -> U+2164 | -> 0x8758 | ROMAN NUMERAL FIVE |
| 0xfa4f | -> U+2165 | -> 0x8759 | ROMAN NUMERAL SIX |
| 0xfa50 | -> U+2166 | -> 0x875a | ROMAN NUMERAL SEVEN |
| 0xfa51 | -> U+2167 | -> 0x875b | ROMAN NUMERAL EIGHT |
| 0xfa52 | -> U+2168 | -> 0x875c | ROMAN NUMERAL NINE |
| 0xfa53 | -> U+2169 | -> 0x875d | ROMAN NUMERAL TEN |
| 0xfa54 | -> U+ffe2 | -> 0x81ca | FULLWIDTH NOT SIGN |
| 0xfa58 | -> U+3231 | -> 0x878a | PARENTHESIZED IDEOGRAPH STOCK |
| 0xfa59 | -> U+2116 | -> 0x8782 | NUMERO SIGN |
| 0xfa5a | -> U+2121 | -> 0x8784 | TELEPHONE SIGN |
| 0xfa5b | -> U+2235 | -> 0x81e6 | BECAUSE |
0xed40 -> U+7e8a -> 0xfa5c CJK Unified Ideograph 0xed41 -> U+891c -> 0xfa5d CJK Unified Ideograph 0xed42 -> U+9348 -> 0xfa5e CJK Unified Ideograph (中略) 0xeef8 -> U+2179 -> 0xfa49 Small Roman Numeral Ten 0xeef9 -> U+ffe2 -> 0x81ca Fullwidth Not Sign 0xeefa -> U+ffe4 -> 0xfa55 Fullwidth Broken Bar 0xeefb -> U+ff07 -> 0xfa56 Fullwidth Apostrophe 0xeefc -> U+ff02 -> 0xfa57 Fullwidth Quotation Mark
情報交換のための文字コード(CES)としてUTF-8を使う場合、交換相手の側でEUC-JPからUTF-8に変換し、こちらでUTF-8からEUC-JPに戻す場合がある。交換相手の変換表がこちらと違う場合を考慮すると、できれば、シフトJIS / EUC-JPとUnicodeとの変換表は、多対1にしておきたい。
例えば0x5c -> U+00a5と変換するようなシステムを考慮すると、次の文字を手当てしておくといい。
| シフトJIS / EUC-JP | Unicode | シフトJIS / EUC-JP | |
|---|---|---|---|
| 0x5c | -> | U+005c REVERSE SOLIDUS | -> 0x5c |
| U+00A5 YEN SIGN | -> 0x5c | ||
| 0x7e | -> | U+007E TILDE | -> 0x7e |
| U+203e OVERLINE | -> 0x7e | ||
| EUC-JP 0xA1BD | -> | U+2014 EM DASH | -> EUC-JP 0xA1BD |
| U+2015 HORIZONTAL BAR | -> EUC-JP 0xA1BD | ||
上記のテストをパスする変換表であれば、現状では、問題が生じないと思う。
Fedora Core 3 Linux (glibc 2.3.3) でiconv()に与えることができるCES名のうち、妥当なもの、不味いものはそれぞれ次のようになる。
| 妥当 | 妥当ではない | |
|---|---|---|
| EUC-JP系 | "EUC-JP-MS", "eucJP-MS", "eucJP-open", "eucJP-win" | "EUC-JPX0213", "EUC-JP", "eucJP", "ujis" |
| シフトJIS系 | "SJIS-open", "SJIS-win", "CP932", "MS932" | "SHIFT-JIS", "Shift_JIS", "Shift_JISX0213", "SJIS", "IBM-932", "IBM932" |
iconv()に実装されている変換表がいずれも不味い場合は、別の変換表を使うしかない。Ruby(v1.8.1まで)では、uconvモジュールにパッチを当てて使うのがいい。uconv
Ruby 1.8.2以降では、標準添付のnkfモジュールがEUC-JP/シフトJIS - Unicode変換できるようになっている。変換表もおおむね妥当なもの。(ただし、EUC-JPのみIBM拡張漢字がサポート外。)
Netsphere Laboratories http://www.nslabs.jp/
[PR]