Skip to content
hama.day

文字コードの基本をUnicodeを中心に改めて整理

文字コードの基本をUnicodeを中心に改めて整理する。

Unicodeは文字コードの一種。

まず前提として、文字をコンピュータで扱うためには各文字を区別する必要がある。そのためにそれぞれの文字に対して符号化した一意な数字(IDのようなもの)を割り振る。その各文字と数字の対応表を文字コード1という。文字コードはUnicodeの他にもASCII, Latain-1やJIS X 0201などがある。

ここで各文字に割り振った数字は符号位置(コードポイント2)と言う。

同じ文字でもどういう符号位置が割り当てられているかは文字コードによって異なる。また、とある文字コードにどういう文字が収録されているか、つまりその文字コードがどの文字を扱っているかも異なる。符号化位置を考慮せずに、文字コードにどういう文字が収録されているか?という文字の集まりにのみ着目したものは文字コードと区別して文字集合(character set)と言う。

その文字集合の中の各文字に符号位置を割り当てているので、文字コードは符号化文字集合(coded character set)と言う。

Unicodeについて

Unicodeの符号位置はU+12ABU+2A456, U+102334というように、U+に続けて4~6桁の16進数で表す。Unicode内にもいくつかの区分(面3)があり、4桁の符号位置の文字の集合は基本多言語面(BMP)と呼ばれる。下位4桁以外の数字で何番目の面か区別できる。4桁であれば00が省略されていると考えて00面(BMP。1番目の面), 5桁の1 ~ F面(2 ~ 16番目の面), 6桁の10面(イチゼロ面)という17個の面がある。それ以降の面(UTF-16で表すことのできない面)は無いものと定義されている。

  • 65536目の文字までのみを想定していた当初のUnicodeで扱える文字集合の範囲: BMP(U+0000 ~ U+FFFF)までを表現できた。
  • サロゲートペアを扱えるUTF-16で表現できる文字集合の範囲: 基本多言語面である00面(U+0000以降) ~ 10面(U+10FFFFまで)までを表現できる。UTF-16で表現できるこのU+10FFFFという制約から、Unicodeはその文字集合の定義の範囲をU+0000 ~ U+10FFFFまでに制限している。

BMPの先頭128番目までで表している文字とその符号位置はASCIIと同様で互換性がある。(バイト列としても完全互換なのはUTF-8のみ)

文字符号化方式

コンピュータが内部で文字を扱うためには符号位置のままでは処理できない。ある文字集合のそれぞれの符号位置をコンピュータが利用できるバイト列(データ列)に変換する、符号化(エンコーディング)という処理を内部で行っている。この符号化をする際に具体的にどのようなバイト列に変換するかはいくつも考えられ、このバイト列に変換する際の一定の規則を文字符号化方式(character encoding scheme. CES)4という。 文字符号化方式にはUTF-8やUTF-16, UTF-32、Shift_JISなどがある。

ある文字符号化方式は全ての文字コードを符号化できるものではなく、とある一定の特定の文字コードを符号化するためのものなので、文字符号化方式から処理対象の文字コードもある程度は特定できる。ある程度と言ったのは例えばShift_JISであればIS X 0201,JIS X 0208,JIS X 0213などの、複数の文字コードのための文字符号化方式となるため。また、UTF-*もUnicodeのための文字符号化方式だが、UnicodeがASCII互換なためにUnicodeかASCIIかの特定は出来ない。基本的には問題に成ることはなさそうだが。

Unicodeの文字符号化方式

Unicodeの文字符号化方式(以下、符号化方式)として代表的なものにUTF-8, UTF-16, UTF-32などがある。

  • UTF-8は8ビット単位の符号化方式で、符号位置の値によって長さが1 ~ 4バイトに変化する可変長。1バイトならASCIIと互換性がある。
  • UTF-16: サロゲートペアを利用する符号化方式。UnicodeやUTF-16の出自から固定長と言い切っている説明もあるが今となっては厳密には、BMPで収まる文字は2バイト、サロゲートペアの文字は4バイトで表現する。
  • UTF-32: 固定長。サロゲートペアを使わず常に32bitでコードポイントを表現する。固定長なので処理はしやすいが、常に32bitなので他の符号化方式よりもファイルサイズが大きくなってしまう。

Unicodeに様々な文字符号化方式が出来ていく流れ

*Unicodeの歴史の特に初期ではISO/IEC 10646の話もあるが、ここでは一旦割愛してユニコードコンソーシアムによって開発されたものを中心に話す。

そもそもUnicodeには当初から複数の符号化方式があったわけでなく、16ビット2バイトの固定長でコードポイントをそのままデータ化していた。(Unicodeが符号化方式も意味していた)。これが後のUTF-16に繋がる。 よって16ビットで表現できる65536文字までの収録を想定していた。65536文字で足りると考えられていたため。この65536文字はのちに基本多言語面として扱われる。

しかし全然足りないことが発覚したので文字を2バイトではなく4バイト固定長で表して対応文字数を拡張することになった。ただし、ここで既に2バイト固定長の前提で動いている既存のシステムとの後方互換性を重視して、今までと同じように単純に4バイトで1文字を表現せず、基本は2バイトで1文字のままで、65536文字に収まらない文字だけ4バイトで1文字とした。

具体的には、この拡張時点で63336文字の領域(BMP)のうちの後半部分は未定義で空いていたので、その後半部分をさらに2つ(前半を上位、後半を下位)に分け、新しく追加する文字についてはこの上位と下位のコードポイントの組み合わせで表現することとした。この上位、下位に分けられたそれぞれのコードポイントをサロゲート文字、サロゲート文字の組み合わせによって結果的に表現される文字がサロゲートペアである。

このようにUnicodeの仕組みを仕切り直し、Unicodeは文字集合としてサロゲートペアという仕組みを入れて文字不足を解消した。

そしてそのサロゲートペアを利用してBMP以降の文字を表現できるものをUTF-16という文字符号化方式とした。また、別のアプローチとして後方互換性を気にせずすべてを32bit固定長で扱おうとしたものがUTF-32。UTF-16のサロゲートペアというややこしさもなく、UTF-32の32bit固定長という冗長でメモリ効率の悪さもない、可変長でASCIIともバイト列として互換になるUTF-8というようにそれぞれが分かれた。

サロゲートペア

基本多言語面のうち、U+D800 ~ U+DBFFの領域は上位サロゲート文字、U+DC00 ~ U+DFFFは範囲は下位サロゲート文字と呼ばれる。これらはサロゲートペアの文字を表現するために、組み合わせて使う特殊な文字。単体では不正なもの。

ここでややこしいのが、サロゲート文字とそれによるサロゲートペアの仕組みはUTF-16でしか利用しない。ただし、サロゲート文字はUnicodeの符号位置としてBMP内に定義されている。つまり、UTF-8やUTF-32ではサロゲート文字ひいてはサロゲートペアの仕組みを利用せずとも直接サロゲートペアの領域の文字を表現できるが、文字として単体では不正で実質使えない不要なサロゲートペアのためのサロゲート文字が存在することになる。

それぞれの符号化方式とバイト数

先で話したようにUTF-32は32bit4バイト固定となるが、UTF-16とUTF-8は可変長。

  • UTF-16
    • BMPで収まる文字は2バイト
    • BMPより後のサロゲートペアの文字は4バイトで表現する。
  • UTF-8の符号位置ごとのバイト数。1 ~ 3が基本多言語面。
    1. U+0000 ~ U+007F のASCII互換の文字: 1バイト
    2. U+0080 ~ U+07FF の文字: 2バイト
    3. U+0800 ~ U+FFFF の文字: 3バイト
    4. それ以降の文字(基本多言語面より後の文字): 4バイト

特にUnicodeの符号位置から、UTF-8のバイト列を調べる際の注意について。U+XXXX というのはあくまでもUnicodeのコードポイントとして U+4~6桁のhexで表現したものであり、そのhexが2バイト(U+0800)のように表記されているからといって、UTF-8のバイト列として2バイトになるわけではない。

具体的に、Unicode符号位置からUTF-8のバイト列に変換する際の変換方法は「プログラマのための文字コード技術入門」で文字符号化方式のUTF-8の節で記載されている。これによると、U+0800E0 A0 80という3バイトのバイト列になる。

UTF-8のASCII互換

U+007FまではUTF-8でASCII互換となる。つまり、UTF-8で記録されたU+007Fまでの文字はASCIIとしても処理できるし、ASCIIのファイルはUTF-8でも処理できる。

参考


  1. 一般的に具体的なとある文字に対する数字のことを指して文字コードと言っている例もよくある
  2. 稀にコードポジションとも
  3. 面の他に区、点、群もあるがここでは割愛
  4. 似た用語に文字符号化形式があるがここでは割愛。
#文字コード#Unicode
© 2023 by hama.day. All rights reserved.