シフトJIS / EUC-JPとUnicodeとの妥当な変換表
2004.10.17 新規作成。2004.12.19 加筆。2005.04.02加筆。
最近、コンピュータで扱う文字列の文字コードがUnicodeでなければならない場面が増えてきた。UnicodeとシフトJIS、EUC-JPを変換する機会が多い。この変換は変換表で行うが、変換表が実際的なものでなければ、文字化けが発生することになる。
おかしな変換表は、これまでは、特にLinuxなどの上で動作するオープンソースソフトウェアで多く見られた。おそらく規格原理主義者が多かったためだろう。そもそも、規格どおりに変換表を作ると、実用的な変換表にはならない。しかし、最近ではまともな変換表を実装しているものも増えてきて、うまく選ぶだけでいいようになってきている。
ソフトウェアごとの変換表とその違いをまとめたページはよく見かけるが、では実際にどのように変換するものを選べばいいか不明なので、まとめてみた。
変換表に求められる条件
このページでは、「文字」を単にコードポイントが与えられて一意に区別できるもの、ぐらいの意味で使う。包摂規準がどうあるべきか、あるいは本質的にコンピュータでの文字とは何であるか、などについては立ち入らない。
実際的な変換表は、できるかぎりround-trip conversionを達成し、なおかつ、異なるシステム上のソフトウェアとの情報交換を考慮したもの、ということになる。
Unicodeと、シフトJIS、EUC-JPとの妥当な変換表は、少なくても次の点を満たしていなければならない。
収録する文字集合と変換
- 0x00〜0x7F のそれぞれの文字について、U+0000〜U+007F (C0 Controls and Basic Latin; JIS X 0211 C0集合 + ISO/IEC 646 IRV) に相互に変換できること。これ以外の文字がU+0000〜U+007Fに変換されないこと。
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 - ISO/IEC 646 IRV、JIS X 0201カタカナ、JIS X 0208漢字集合に含まれる文字をすべてUnicodeの別のコードポイントに変換し、かつシフトJIS、EUC-JPに戻したときにすべて元のコードポイントに戻ること。
IRVとJIS X 0208には同じ文字(例えばスラッシュ'/')が含まれ、またJIS X 0201とJIS X 0208にも同じ文字が含まれている(カタカナ)。本来は文字ではなく書式の話だが、現実には、JIS X 0208は全角として、JIS X 0201は半角として表示するように期待されているので、別の字として扱う必要がある。
- NEC特殊文字、IBM拡張文字、NEC選定IBM拡張文字をサポートしていること。
丸囲み数字などが含まれた、既存の大量の文書を捨てるわけにはいかない。IBM拡張文字についても同じ。round-trip conversionを維持すること。
- JIS X 0212補助漢字、JIS X 0213漢字集合
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を放棄し、次のように変換したほうがいい。
- NEC特殊文字のうちJIS X 0208にもある文字は、Unicodeからの変換ではJIS X 0208のほうへ変換する。
シフト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 - IBM拡張文字のうちJIS X 0208にもある文字はJIS X 0208のほうへ、NEC特殊文字にもある文字はNEC特殊文字のほうへ変換する。
シフト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 - NEC選定IBM拡張文字は、Unicodeからの変換ではIBM拡張文字のほうへ変換する。ただし、シフトJISで0xeef9は、JIS X 0208にもあるので、JIS X 0208のほうへ変換する。
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拡張漢字がサポート外。)
外部リンク
- [PRB] SHIFT - JIS と Unicode 間の変換問題
- Windows(CP932)においてUnicodeと相互変換できない文字の一覧。
- コード変換規則
- eucJP-openとUCS (Unicode) との間のコード変換規則。
- 標準情報(TR) TR X 0015:2002 XML日本語プロファイル
- シフトJIS / 日本語EUCのバリエーションについて