2014年2月25日火曜日

Unicodeのコードポイントとエンコーディング

Joel on Software を読んでて、どうもUnicodeについてよく分かってなかったことに気づいた。とうことで、まとめておこうと思う。

コードポイント

まず、Unicodeでは全ての文字に対してコードポイントと呼ばれるものが割り当てられている。例えば、アルファベットの A には U+0041 というコードポイントが割り当てられている。U+はUnicodeを意味し、後に続く数字は16ビットの16進数だ。「Hello」という単語はコードポイントで表すと、

H → U+0048
e → U+0065
l → U+006C
l → U+006C
o → U+006F

のようになる。コードポイント自体は、メモリ上に保持されたりファイルに記録されたりするデータの形式とは関係がない。コードポイントをどのようにデジタルデータとして具体化させるかを決めるのがエンコーディングだ。

エンコーディング

前述のように、コードポイント自体は文字のIDみたいなもので、それを具体的にどういうデジタルデータで保持するのかを決めなければならない。それがエンコーディングだ。

まず、コードポイントの16ビットの数字をそのままデータとして保持するのが「UTF-16」または「UCS-2」(2バイトだから)と呼ばれる。データはこうなる(16進数)。

H → U+0048 → 00 48
e → U+0065 → 00 65
l → U+006C → 00 6C
l → U+006C → 00 6C
o → U+006F → 00 6F

なお、上位8ビットと下位8ビットを入れ替える事も有り得る。CPUのアーキテクチャによっては、そのほうが処理が速い場合があるからだ。その場合はこうなる(16進数)。

H → U+0048 → 48 00
e → U+0065 → 65 00
l → U+006C → 6C 00
l → U+006C → 6C 00
o → U+006F → 6F 00

ビットを入れ替えたことを示すために、文字列の先頭に FF FE をつけるようにした。これはバイトオーダーマーク(BOM)と呼ばれ、これがBOM付きUTF-16だ。

ところが、UTF-16だと、英語ではコードポイント127以下(U+0000〜U+007F)しか使わないので、常に一文字に16ビット(2バイト)割り当てるのはもったいない。そこで、0~127(U+0000〜U+007F)のコードポイントは8ビット(1バイト)で表現することにし、それ以上のコードポイントをは頭に特定のビット列をつけることにより表現することにしたのが UTF-8 だ。ちなみに「Hello」のデータはこうなる(16進数)。

H → U+0048 → 48
e → U+0065 → 65
l → U+006C → 6C
l → U+006C → 6C
o → U+006F → 6F

UTF-8においては、コードポイントU+0000〜U+007F は1バイトで、前頭のビットは 0 になる(0xxxxxxx)。コードポイントU+0080〜U+07FF は2バイトで、最初のバイトの先頭は110、次のバイトの先頭は10と決められていて、空いたビットにコードポイントが入る(110xxxxx 10xxxxxx)。同様にして、コードポイントU+0800〜U+FFFF は3バイトで、最初のバイトの先頭は1110、後続の2バイトの先頭は10である(1110xxxx 10xxxxxx 10xxxxxx)。

例えば、日本語の「おはよう」のデータはこうなる(2進数)。

お → U+304a → 11100011 10000001 10001010
は → U+306f → 11100011 10000001 10101111
よ → U+3088 → 11100011 10000010 10001000
う → U+3046 → 11100011 10000001 10000110

わかりにくいかもしれない。最初の文字「お」を詳しく見てみよう。
3バイトだが、こうなっている。
11100011 10000001 10001010
UTF-8としての規則であるビットを黄色く塗ってみた。これを除いて、4ビットごとに区切り直してみるとこうなる。
11100011 10000001 10001010

0011 0000 0100 1010
これは、16進数に直せば
304a
となる。すなわち「お」のコードポイントU+304aを表現しているのだ。

とうことで、Unicodeのコードポイントとエンコーディングについてざっとまとめてみた。エンコーディングはここで挙げたもの以外にも数多くあるので、興味があったら調べてみるといいと思う。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

0 件のコメント:

コメントを投稿