Unicodeについて

Unicodeで日本語が該当する箇所
Unicodeの中で日本語が該当する所を調べてみました。
漢字は基本的に、日本語で使われるか中国語で使われるかは区別されません。ですからこれらの範囲の中には中国でしか使われない漢字も含まれています。
ここでは割り当てられている領域を書いています。実際に文字が割り当てられている範囲が書かれている資料とは終わりの値が若干異なることがあります。

ひらがなU+3040~U+309F(ひらがな文字は U+3041~U+3096)
カタカナU+30A0~U+30FF(カタカナ文字はU+30A1~U+30FA)
「CJK統合漢字」U+4E00~U+9FFFに、約20,000字
「CJK統合漢字拡張A」U+3400~U+4DBFに、6,500字強
「CJK統合漢字拡張B」U+20000~U+2A6DFに、約42,000字
「CJK統合漢字拡張C」U+2A700~U+2B73F(2009年10月制定のUnicode5.2.0)
「CJK統合漢字拡張D」U+2B740~U+2B81F(2010年10月制定のUnicode6.0)

また、一覧の中から私が目視で日本語ぽいと判断したものに
U+2E80-2EFF CJK部首補助
U+2F00-2FDF 康熙部首
U+3000-303F CJKの記号及び句読点
U+31F0-31FF 片仮名拡張
U+3200-32FF 囲みCJK文字・月
U+3300-33FF CJK互換用文字
U+FE30-FE4F CJK互換形(たてがき?)
U+FE50-FE6F小字形(たてがき?)
U+FF00-FFEF半角・全角形
があります。

漢字ではこれらの「CJK統合漢字」や「CJK統合漢字拡張A~D」とは別に、
U+F900~U+FAFFとU+2F800~U+2FA1Fに「互換漢字」
U+E0100〜U+E01EFにIVS用のバリエーション符号
があります。

Objective-CでのUnicode文字列の扱い
iOSの文字列の文字コードはUnicodeです。Unicodeには表現方法がいくつかあって、おそらく、UTF-16という方法を用いていると思います。(はっきりした資料が見当たらず予想という前程)
このUTF-16はほとんどの文字を2バイトで表現しますが一部の文字を4バイトで表現します。
困ったことに、NSStringのlengthメソッドやcharacterAtIndexメソッドはすべての文字を2バイト文字とみなして実行されるようです。

つまり
NSString *strに4バイトで表現される文字を1文字入れたとすると、
NSLog(@"%d",[str length]);//2が表示されます
NSLog(@"%x",[str characterAtIndex:0]);//片方の2バイトの値が表示されます
NSLog(@"%x",[str characterAtIndex:1]);//もう片方の2バイトの値が表示されます
となります。

UTF-16で表現した時に2バイトや4バイトになるのが煩わしい場合、あらかじめ全てをUTF-32にして、4バイトに統一しておくやり方もあります。
charポインタで扱う場合、
const char *str32 = [str cStringUsingEncoding:NSUTF32StringEncoding];
また、NSDataで扱う場合には
NSData *str32Data = [[NSData alloc] initWithBytes:[str cStringUsingEncoding:NSUTF32StringEncoding]
length:[str lengthOfBytesUsingEncoding:NSUTF32StringEncoding]];
(ここでは文字列最後の\0の値は入れていません。)

Unicodeの表記
Unicodeの文字を表現する場合、"U+"にその文字の符号位置を表す16進数の値を続ける。この値をコードポイントと言う。 BMP はU+0000 - U+FFFF の 4 桁に対応し、21 ビットの空間は U+0000 - U+10FFFF であり、必要に応じて 5、6 桁で表す。
文字とU+〇〇〇〇が1対1に対応するとかと思ったら、中にはUnicode独自の制御符号にU+〇〇〇〇という表記がされるものもある。UTF-16のサロゲートペアの値などがそうらしいのだが、これは文字では無く制御符号の要素が強いので、それをU+表記するとU+の定義がぶれるような気がするが、私だけかもしれない。

UnicodeとJIS
過去20年くらいで共にじわじわと仕様が上がっていった。UnicodeはUnicode3.2(2002年)でJIS X 0213に正式対応しました。

UTF-32は最強か
UTF-16の弱点であるサロゲートペアを考慮しないでプログラム出来るやりかたとして、UTF-32を挙げたがこれは最強だろうか?IVSの扱いが気になるので調べてみる。IVSとはちょっと異なる文字を区別する手段。
渡邊に邊はいくつか種類があり、UnicodeではIVSによって区別する。
この内一つは基本部分がU+908A。異体字セレクタ部がU+E0101。
これをUTF-32で表すと32ビットになるか?(うまいこと処理して32ビットに収めるか?)
やってみると
0x0000908A000E0101
残念ながらIVS使用字は基本の字と異体字セレクタをそのままつなげた64ビット。
まあこれを32ビットに詰め込もうとすると計算が混乱する結果になりそうなのでどっちもどっちという気がする。

ドイツ語やフランス語などのUnicodeの初めの127に入ってない文字
長い文字列に区切りを入れる処理を行う際、日本語のように基本的にどこで区切っても意味は通じるものか、単語の途中で区切っては意味が崩壊するものかというのを判断する必要がある。Unicodeの初めの127(基本ラテン文字とかASCII文字コードなどと言われる)にある文字なら一覧表を見ればすぐにわかるのだが、例えばドイツ語で用いられるウムラウト系の文字は初めの127には入っていない。こういった区切ってはいけない文字がUnicodeのどこにあるかを把握しておきたい。ただ、Unicodeの文字は大量にあるので、区切ってはいけない文字を全てピックアップしようとすると大変なので、ある程度の認識精度で妥協する。
まずはフォントのデータを調べる。文字列をあるフォントで表示しようとした際、そのフォントにないものは別のフォントになる。記号などが別のフォントになっていてもあまり違和感はないが、単語内の一文字だけが別のフォントになっていれば違和感がある。これを避けるようにフォントに収録する文字を選んでいると思われる。区切ってはいけない文字を全てピックアップするという目的には、まず既存のフォントのデータを調べて、大体の目安をつけようという魂胆である。
いくつかのフォントを見てみると
U+0080-00FFラテン1補助
U+0100-017Fラテン文字拡張A
U+0180-024Fラテン文字拡張B
U+0370-03FFギリシア文字及びコプト文字
U+0400-04FFキリール文字(キリル文字)
U+1E00-1EFFラテン文字拡張追加
このあたりを押さえておくのが基準ラインらしい。

http://homepage2.nifty.com/k_maeda/code/uni/index.htmlを利用して細かく見ていくと

U+0080-00FFラテン1補助
00C0-00FFに文字がある。
ただし、00D7は算数の掛ける記号、00F7は割る記号なので省いてもいいかも。

U+0100-017Fラテン文字拡張A
ここは全体的に文字

U+0180-024Fラテン文字拡張B
一部記号のようなものもあるが、全体的に文字

U+0370-03FFギリシア文字及びコプト文字
一部記号のようなものもあるが、全体的に文字

U+0400-04FFキリール文字(キリル文字)
一部記号のようなものもあるが、全体的に文字

U+1E00-1EFFラテン文字拡張追加
ここは全体的に文字

一部の記号のようなものをどうするかを調べるのは大変なので以上の範囲にあるものはすべて、区切ってはいけない文字ということで妥協する。

参考
東アジア文字のコード表
http://www.asahi-net.or.jp/~ax2s-kmtn/ref/unicode/e_asia.html

文字コード規格JIS X 0213の制定および改正で委員を務めた方の記事
日本の文字とUnicode

コメント

このブログの人気の投稿

Swiftのコンパイルエラー寄せ集め

Swift2.2からSwift3.0への変換を行ってみて

AVAudioSession細かいことまとめ(late 2014)