既存の日本語文字コードと Unicode の間のマッピングルール
目次
- はじめに
- 関連リンク
- Unicode-1.1 : ASCII <-> Unicode
- Unicode-1.1 : JISX0201, JISX0208, JISX0212 <-> Unicode
- 日本語 EUC エンコーディングの問題
- JISX0221-JISX0201
- JISX0221-ASCII
- Windows における変換
- Sun の JDK における変換
- mule-ucs における変換
- Be-OS における変換
- ベンダ定義文字の問題
- JIS エンコーディングの問題
- JIS エンコーディングにも対応した変換
- Qt-2.0 のサポート状況
- 半角/全角の問題
- その他の問題
- 感想
- ソースコード
はじめに
Qt 2.0 に既存の日本語文字コードと Unicode の間の変換クラスを突っ込もうと思って調べはじめたら想像以上にややこしいことになっていてはっきり言ってお手上げ状態なんですが、とりあえず調べたところまではまとめておくかな、ということでページを作ってみました。こんなものでも何かの参考になれば幸いです。ここでは ASCII, JIS, EUC, ShiftJIS, Unicode について知っていることを前提としています。
このページでは 0x1234 のように書いてあるものは既存の文字コードを 16 進数で表したもの、 U1234 のように書いてあるものは Unicode を 16 進数で表したものです。 通常は Unicode は U+1234 のように書くんですが、最初に図を書く時に U1234 って書いちゃって修正するのが面倒なのでこれで行きます(^^;。
抜けや間違い等を発見した場合は hc3j-tkg at asahi-net.or.jp までご一報下さいm(_ _)m。
関連リンク
- Unicode Consortium
- ISO/IEC 10646 - UCS
- XML 日本語プロファイル <-XML で日本語を扱う際の諸々をまとめた標準情報(TR)
- 文字コード問題を考える
- CDE/Motif 技術検討 WG
- Unicode とユーザ定義文字・ベンダ定義文字に関する問題点と解決策
- XKP : Windows NT eXtended Kanji Processing
- 従来の文字コードと Unicode の対応に関する諸問題 <-このページと同じことをより丁寧に解説しています(このページを作った後に発見した(^^;)。
- シフトJISからUnicodeへの変換テーブルの相違
- 日本語の Unicode ベンダ依存文字表
- IBM developerWorks の Unicode zone
- 文字
- 文字コードの話
- 日本語と文字コード
- japanese font, charactor code / 日本語フォント、文字コード
- 安岡孝一さんのページ
- 池田証寿さんのページ
- eKanji home page
- LV
- UNICODE (コードと字形)
- Java Internationalization & Multilingualization
- 7ビット及び8ビットの2バイト情報交換用符号化漢字集合 - 第三水準および第四水準
- Java Internationalization & Multilingualization
- Unicode in the Unix Environment
- Unicode リンク集
関連雑誌記事
- ASCII 1998年6月号 P.269-275 「漢字文化は危なくない」
- ASCII 1998年12月号 P.477-481 「Unicode を巡る放談会」
参考文献
Unicode-1.1 : ASCII <-> Unicode
まずは ASCII コードについてですが、これはなんてことはなくて、 0x20~0x7e まで (制御コードも含めると 0x00~0x7f まで) がそのまま U0020~U007e (U0000~U007f) にマップされます。
Unicode-1.1 : JISX0201, JISX0208, JISX0212 <-> Unicode
次は Unicode 1.1 の仕様に従った場合の JISX0201, JISX0208, JISX0212 のマッピングですが、JISX0208, JISX0212 については順不同で Unicode にマップされるので詳細については省略します。ここでのポイントは以下の点です。- JISX0201 の 0x20~0x7e まで (制御コードも含めると 0x00~0x7f まで) は、二つの例外を除いて、ASCII と同じく U0020~U007e (U0000~U007f) にマップされます。
- JISX0201 の 0x5c は ASCII の 0x5c と違って U00a5 (Yen Sign) にマップされます。
- JISX0208 の 0x2140 ('\') は U005c (Reverse Solidus) にマップされます。
- JISX0201 の 0x7e は ASCII の 0x7e と違って U203e (Overline) にマップされます。
- JISX0212 の 0x2237 ('・') は U007e (Tilde) にマップされます。
日本語 EUC の問題
さて、Unicode-1.1 のマッピングルールに従った場合、JISX0201 + JISX0208 である ShiftJIS を Unicode に変換するのには特に問題はありません。しかし、ASCII + JISX0201 Kana + JISX0208 + JISX0212 である日本語 EUC を Unicode に変換しようとすると下の図のように U005c と U007e で衝突が起こってしまします。この時点で既に Unicode-1.1 の規格では問題があって、既存の日本語文字コードを扱うには不十分だと言えます。そこで、この問題をどうやって回避するか、なんですが…これが困ったことにプラットフォームによって様々なのです。
オープングループ の 日本ベンダ協議会 の CDE/Motif 技術検討 WG が Unicode とユーザ定義文字・ベンダ定義文字に関する問題点と解決策 を公開しています。その コード変換規則 について見てみます。
JISX0221-JISX0201
JISX0221 で 0x20~07e を JISX0201 とみなす場合のマッピングルールで、事実上、ShiftJIS <-> Unicode 用のマッピングルールでしょう。 Unicode-1.1 とは 0x213d ('―') が U2015 (Horizontal Bar) ではなくてU2014 (Em Dash) にマップされる点だけが異なっています。 私にはどちらが好ましいのかは分かりません。 というか、どっちでも良いから一つに決めてくれ、というか。
JISX0208 | Unicode-1.1 | JISX0221-JISX0201 |
0x213d ('―') | U2015 (Horizontal Bar) | U2014 (Em Dash) |
JISX0221-ASCII
JISX0221 で 0x20~07e を ASCII とみなす場合のマッピングルールで、事実上、日本語 EUC <-> Unicode 用のマッピングルールでしょう。 U005c, U007e での衝突を避けるために JISX0208 の 0x2140 ('\') が Uff3c (Fullwidth Reverse Solidus) に、 JISX0212 の 0x2237 ('・') が Uff5e (Fullwidth Tilde) にマップされます。それ以外に、JISX0221-JISX0201 と同様に JISX0208 の 0x213d ('―') が U2015 (Horizontal Bar) ではなくてU2014 (Em Dash) にマップされるのに加えて、 JISX0208 の 0x2131 (' ̄') が U203e (Overline) に、0x216f ('¥')が U00a5 (Yen Sign) にマップされる点が Unicode-1.1 と異なっています。JISX0201 の代わりに ASCII を採用することで U00a5 と U203e が空きになるのですが、なぜわざわざそこを埋めなければならないのでしょう…? SJIS -> Unicode -> EUC あるいは EUC -> Unicode -> SJIS と変換した時のことを考えているのかと思ったんですが、例えば SJIS JISX0201 0x5c -> U00a5 -> EUC JISX0208 0x216f とすると半角円記号が全角円記号になっちゃいますし、あるいは SJIS JISX0208 0x216f -> Uffe5 -> EUC × とすると全角円記号がどこにもマップされないということになっちゃいますし…。
その後考えたのですが、Unicode がまずあってそれを既存の文字コードにマッピングする場合に U00a5 (Yen Sign) をマップする先がないというのが問題なのではないでしょうか。でも、そうだとしたら Uffe5 (Fullwidth Yen Sign) にもマップする先がないとまずいですよね…う~ん、そうすると今度は1対1対応でなくなっちゃうか。その辺はユーザの側で適宜対応してね、ということになるのでしょうか。
JISX0208 | Unicode-1.1 | JISX0221-ASCII |
0x2131 (' ̄') | Uffe3 (Fullwidth Macron) | U203e (Overline) |
0x213d ('―') | U2015 (Horizontal Bar) | U2014 (EM Dash) |
0x2140 ('\') | U005c (Reverse Solidus) | Uff3c (Fullwidth Reverse Solidus) |
0x216f ('¥') | Uffe5 (Fullwidth Yen Sign) | U00a5 (Yen Sign) |
JISX0212 | Unicode-1.1 | JISX0221-ASCII |
0x2237 ('・') | U007e (Tilde) | Uff5e (Fullwidth Tilde) |
Windows における変換
従来の文字コードに ShiftJIS を使っているということで JISX0201 + JISX0208 ( + 外字) <-> Unicode というマッピングルールです。が、いろいろ変です。 JISX0201 の 0x5c が ASCII の 0x5c と明確に区別されることなくパス名の区切り記号として使われている & バイナリレベルでアプリケーションの互換性を保たなければならないために JISX0201 0x5c を U005c にマップするということをやっています。 JISX0208 の 0x2140 ('\') が Uff3c (FULLWIDTH REVERSE SOLIDUS) に、JISX0212 の 0x2237 ('・') が Uff5e (FULLWIDTH TILDE) にマップされるのはいいのですが、それ以外に、どういうわけか JISX0208 の '~', '∥', '-', '¢', '£', '¬' と JISX0212 の '・' が Unicode-1.1 と違うマッピングとなっています。 これらの文字が化けるという経験をしたことがある方は結構いるのではないでしょうか?このあたりは XKP でも認識していて Microsoft に要望として出しているようですが、いまさら変更するようなことは恐らくしないでしょうねぇ。
JISX0201 | Unicode-1.1 | Windows |
0x5c | U00a5 (Yen Sign) | U005c (Reverse Solidus) |
0x7e | U203e (Overline) | U007e (Tilde) |
JISX0208 | Unicode-1.1 | JISX0221-ASCII |
0x2140 ('\') | U005c (Reverse Solidus) | Uff3c (Fullwidth Reverse Solidus) |
0x2141 ('~') | U301c (Wave Dash) | Uff5e (Fullwidth Tilde) |
0x2142 ('∥') | U2016 (Double Vertical Line) | U2225 (Parallel To) |
0x215d ('-') | U2212 (Minus Sign) | Uff0d (Fullwidth Hyphenminus) |
0x2171 ('¢') | U00a2 (Cent Sign) | Uffe0 (Fullwidth Cent Sign) |
0x2172 ('£') | U00a3 (Pound Sign) | Uffe1 (Fullwidth Pound Sign) |
0x224c ('¬') | U00ac (Not Sign) | Uffe2 (Fullwidth Not Sign) |
JISX0212 | Unicode-1.1 | JISX0221-ASCII |
0x2237 ('・') | U007e (Tilde) | Uff5e (Fullwidth Tilde) |
0x2243 ('・') | U00a6 (Broken Bar) | Uffe4 (Fullwidth Broken Bar) |
Sun の JDK における変換
Java では char 型が C/C++ のように 8bit ではなくて 16bit で Unicode を表します。ということでどういう変換を行っているか見てみると… EUC, JIS, SJIS ともサポートする必要があるためにか、これまた独自のマッピングルールを採用しています。- ASCII と JISX0201 Latin は同じ扱いとする。
- U00a5, U203e が空きになるが、JISX0201 から変換された Unicode ではこれらが出てくることがあるので、Unicode -> ASCII の単方向のみそれぞれ 0x5c, 0x7e にマップする。と思ったら、U00a5 -> 0x5c はあるけど U203e -> 0x7e はないみたい。
- JISX0208 0x2140 ('\') は ASCII との衝突を避けるために Uff5c にマップする。
- JISX0212 0x2237 ('・') が U007e にマップされるが、未対応。 恐らく JISX0212 は誰も使ってないので誰も困ってなくて誰も Sun に報告してないのでそのままになっているんじゃないかと勝手に想像してます(^^;。
JISX0201 | Unicode-1.1 | Sun JDK |
0x5c | U00a5 (Yen Sign) | U005c (Reverse Solidus) |
0x5c | <- | U00a5 (Yen Sign) |
0x7e | U203e (Overline) | U007e (Tilde) |
0x7e | <- | U203e (Overline) |
JISX0208 | Unicode-1.1 | JISX0221-ASCII |
0x2140 ('\') | U005c (Reverse Solidus) | Uff3c (Fullwidth Reverse Solidus) |
Bug Parade で JIS をキーに検索するといろいろ出てきますので興味のある方はどうぞ。 Windows で JISX0208 の '~', '∥', '-', '¢', '£', '¬' が化けることがあるという問題は Java のレベルで解決する類のものではない、としているようです。
mule-ucs における変換
mule-ucs-0.01.tar.gz について調べてみたところ、 Unicode-1.1 の規則をそのまま採用しているようです。Be-OS における変換
伊藤隆幸さんが News にFrom: yuki@dayo.ne.jp (ITO Takayuki) Newsgroups: fj.os.beos Subject: BeOS Unicode conversion survey Date: 07 Mar 1999 18:33:07 GMT Message-ID: <7bugqd$5af$2@horse.fsinet.or.jp>という記事をポストされていますが、マッピングルールの問題、入力メソッドの問題、フォントの問題、文字幅の問題が重なっていろいろ苦労されているようです。
ここではその記事から分かる範囲でとりあえずマッピングルールについてのみ見てみます。 U005c が半角円記号に、U007e が Tilde に見えるということからすると、 ASCII と JISX0201 Latin を特に区別しているわけではなさそうです。 JISX0208 については、次の点が問題になっているようです。
- 0x2140 ('\') が U005c (Reverse Solidus) にマップされているのは Unicode-1.1 と同じですが、Unicode -> JIS では U005c -> 0x005c となって元の 0x2140 に戻りません。
- 0x2141 ('~') が U301c (Wave Dash) ではなく Uff5e (Fullwidth Tilde) にマップされます。
- 0x215d ('-') が U2212 (Minus Sign) ではなく U002d (Hyphen-minus) にマップされていますが、Unicode -> JIS では U002d -> 0x002d となって元の 0x215d に戻りません。
- 0x2160 ('÷') が U00f7 (Division Sign) にマップされているのは Unicode-1.1 と同じですが、Unicode -> JIS では U00f7 -> 0x00f7 となって元の 0x2160 に戻りません。
- 0x217b ('○') が U25cb (White Circle) ではなく U25ef (Large Circle) にマップされます。
ベンダ定義文字の問題
NEC 特殊文字と IBM 拡張文字に関してですが、 JISX0208 と NEC 特殊文字の両方に入っている文字があったり、 NEC 特殊文字と IBM 拡張漢字の両方に入っている文字があったりします。これについては XKP から入手できる WindowsNT 拡張漢字処理仕様書 2.1 の 5.1.2 重複符号文字の対応関係 のところにまとめてあるのでそちらをご覧頂くのがよろしいかと。JIS エンコーディングの問題
ISO-2022-JP では ASCII, JISX0201 Latin, JISX0208 (ISO-2022-JP-2 ではそれに加えて JISX0212) が混在する可能性があるため、Unicode 上でこれら全てが区別できなければなりません。残念ながら上記のマッピングルールはいずれもこの条件を満たしていません。- Unicode-1.1 : 既に指摘したように ASCII と JISX0208, JISX0212 との混在ができません。
- JISX0221-JISX0201 : ASCII を加えると U005c, U007e で衝突が発生します。
- JISX0221-ASCII : JISX0201 を加えると U00a5, U203e で衝突が発生します。
- Microsoft : ASCII と JISX0201 Latin を区別できません。また、Uff5e で衝突が発生しています。
- Sun JDK : ASCII と JISX0201 Latin を区別できません。また、U007e で衝突が発生しています。
- Be-OS : U002d, U005c で衝突が発生しています。
JIS エンコーディングにも対応した変換
Java と同じく EUC, JIS, SJIS ともサポートする方向で、 ASCII, JISX0201 Latin, JISX0208, JISX0212 と Unicode の間で1対1に対応が取れるように、と考えると以下のようなマッピングルールを採用するのが妥当かと思うのですがいかがでしょうか。
半角/全角の問題
工事中です。その他の問題
工事中です。Qt-2.0 のサポート状況
とりあえずメジャーどころとして Unicode-1.1, JISX0221-JISX0201, JISX0221-ASCII, Windows, Sun それに JIS エンコーディングにも対応した変換 をサポートしています。 というか、サポートするようにしました:-)。 また、 Unicode とユーザ定義文字・ベンダ定義文字に関する問題点と解決策 の コード変換規則 に従う形で NEC 特殊文字, IBM 拡張漢字, ユーザ定義文字もサポートしています。感想
内部文字コードとして Unicode を採用した場合について考えると…- I18N のための code set としては Unicode-1.1 は(多少 Know-How は必要だが)一応使える。
- CJKV を含む M17N のための code set としては Unicode-1.1 は単独では使えない。 M17N に使おうと思ったら Unicode の文字列に何らかの形で言語情報等を付加する必要がある。
- M17N ではなく I18N のために使うのであれば同時に一つの言語についてのみ考えればいいわけで、 CJK その他いろいろな言語が入り混じっていて巨大なテーブルを用意しないと変換できない Unicode を使わなくても、 16bit のところに JIS コードなら JIS コードをそのまま突っ込んでやってもいいんじゃないかな? ISO-8859-1 と重なるところだけ揃えてやれば実用上問題になることはあまりなさそうな気がしますが…。
- Unicode-3.0(?) には言語タグ、異字体タグが入るそうで、そうなると CJKV を含む M17N にも使えるようになるのかな?
ソースコード
- C で書いた JISX0201, JISX0208, JISX0212 <-> Unicode-1.1 のコンバータ
- C で書いた JISX0201, JISX0208, JISX0212 に NEC 特殊文字と IBM 拡張漢字を加えたもの <-> Unicode-1.1 のコンバータ
- Unicode-1.1, JISX0221, Windows, Sun, JIS エンコーディングにも対応した変換方式をサポートする C++ のコンバータ
戻る
댓글 없음:
댓글 쓰기