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 (妥当) |
---|---|---|
0x5C | U+00A5 YEN SIGN | U+005C REVERSE SOLIDUS |
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を維持すること。
多重符号化については後述。
EUC-JPでは, JIS X 0212補助漢字をサポートすること。JIS X 0213:2004漢字集合 (これはJIS X 0208と互換性がない.) は、現段階ではサポートする必要はないと思う。
NEC特殊文字にはJIS X 0208に含まれる文字があり (多重符号化)、また, NEC選定IBM拡張文字も, IBM拡張文字から記号と漢字を選んでいるので, 完全に被っている。
IBM拡張文字(388文字) | ||||||
NEC選定IBM拡張文字(374文字) | NEC特殊文字 (83文字) | |||||
373文字 ⅰⅱⅲⅳⅴⅵⅶⅷⅸⅹ¦'" | 13文字 ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ№℡㈱ | 61文字 ①②③④⑤⑥⑦⑧⑨⑩ ⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳ ㍉㌔㌢㍍㌘㌧㌃㌶㍑㍗ ㌍㌦㌣㌫㍊㌻㎜㎝㎞㎎ ㎏㏄㎡㍻〝〟㏍㊤㊥㊦ ㊧㊨㈲㈹㍾㍽㍼∮∑∟ ⊿ | ||||
1文字 ¬ | 1文字 ∵ | 8文字 ≒≡∫√⊥∠∩∪ | ||||
6869文字 (省略) | ||||||
JIS X 0208:1990(6879文字) |
これらについては、Unicodeプライベート領域 (Private Use Area; PUA, U+E000〜U+F8FF) などを駆使して別の文字に変換する手もあるが、他システムとの情報交換を考慮すると、round-trip conversionを諦めざるをえない。
Unicode からの変換では, 次のように寄せたほうがいい。
シフト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, UTF-16を使う場合、交換相手の側でEUC-JPからUTF-8/16に変換し、こちらで 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, SJIS 0x815c |
上記のテストをパスする変換表であれば、現状では、問題が生じないと思う。
結論としては、「シフトJIS」については「マイクロソフト標準キャラクタセット」 (Windows-31J
, MS932
) がよい。歴史的に "cp932
" は, IBMのコードページの場合があるので、注意が必要。
EUC-JPについては eucJP-open がよいが、これは変換表ではない。eucJP-ms
, eucJP-0201
または eucJP-ascii
のうちどれか、となっている。 eucJP-0201
は妥当ではないので、明示的に eucJP-ms
か eucJP-ascii
を指定すべき、となる。
Unicode とユーザ定義文字・ベンダ定義文字に関する問題点と解決策 TOG/JVC CDE/Motif 技術検討 WG.
Fedora Core 3 Linux (glibc 2.3.3) で iconv()
に与えることができるCES名のうち、妥当なもの、不味いものはそれぞれ次のようになる。
(2019.7) Fedora 30 Linux (glibc 2.29) で更新.
妥当 | 妥当ではない | |
---|---|---|
EUC-JP系 | "EUC-JP-MS", "eucJP-MS", "eucJP-win" | CSEUCPKDFMTJAPANESE , EUC-JISX0213 , EUC-JP , eucJP , ujis - NEC特殊文字の一部をサポートしない。
|
シフトJIS系 | "SJIS-open", "SJIS-win", "CP932" *1, "MS932", Windows-31J , CSWINDOWS31J
| CSSHIFTJIS , SHIFT-JIS , Shift_JIS , ShiftJISX0213 , SHIFT_JISX0213 , SJIS - IRVが不正
|
"Shift_JIS
" のようなシフトJISっぽい名前のほうが不味い表になっていることに注意しよう。
SJIS-win
, eucJP-win
は PHP 由来か? 合意された定義か怪しい。
SJIS-open
は、上述の eucJP-open との対比で定められたもの。マイクロソフト標準キャラクタセット (Windows-31J, MS932) と同じ。
iconv()
に実装されている変換表がいずれも不味い場合は、別の変換表を使うしかない。Ruby(v1.8.1まで)では、uconv
モジュールにパッチを当てて使うのがいい。uconv
Ruby 1.8.2以降では、標準添付のnkfモジュールがEUC-JP/シフトJIS - Unicode変換できるようになっている。変換表もおおむね妥当なもの。(ただし、EUC-JP のみIBM拡張文字がサポート外。)
(2019.7) UnicodeライブラリのデファクトスタンダードであるICUで、妥当な変換表を得るには、次の名前を与えること。
妥当 | 妥当ではない | |
---|---|---|
シフトJIS系 | ibm-943_P15A-2003 , windows-31j , csWindows31J , ms932 , CSSHIFTJIS , SJIS
- 全部同じ変換表。
| IBM-932 - 1999版. 収録文字が少ない.
|
EUC-JP系 | CSEUCPKDFMTJAPANESE , EUC-JP , EUCJP , UJIS - IBM拡張文字が89区から92区 (0xF9 - 0xFC; NEC選定IBM拡張文字の位置) が優先されるが、ほかは妥当。
| ibm-954 , ibm-33722_VPUA - NEC特殊文字が全滅. JIS X 0208記号も足らない.
|
glibc と変換表が異なる。
(2019.7) シフトJIS "ms932
" で、チルダ、波ダッシュの変換が怪しい。
シフトJIS | -> Unicode | -> シフトJIS |
---|---|---|
0x7e | U+007E TILDE | 0x7e |
0x8160 | U+FF5E FULLWIDTH TILDE | 0x8160 |
-- | U+301C WAVE DASH | n/a (変換先なし) |
JIS X 0212補助漢字にはチルドがある。
eucJP-ascii
a1 c1 | => U+301C WAVE DASH |
8F A2 B7 | => U+FF5E |
eucJP-ms
a1 c1 | => U+FF5E FULLWIDTH TILDE |
8F A2 B7 | => U+FF5E |
eucJP-ms
のほうは、両方を U+FF5E にマッピングしてしまっている。