名前


UTF-8 - ASCII と互換性のある多バイト Unicode の符号化

説明


ユニコード (Unicode) 3.0 文字集合は 16 ビットのコード空間を占める。 最も単純な Unicode の符号化方法 (UCS-2) では、文字は 16 ビット・ワード (16 ビット文字の列) で構成される。 この列には、 特殊な意味を持つ 16 ビット文字が含まれることがある。 さらに、ほとんどの UNIX ツールは ASCII ファイルを入力として期待するので、 大幅な変更なしには 16 ビットワードを文字として読むことができない。 これらの理由から、 UCS-2 はファイル名・テキストファイル・環境変数などに用いる、外部用の Unicode 符号としては不適切である。 Unicode のスーパーセットである ISO 10646 Universal Character Set (UCS) は 31 ビットのコード空間を占めるが、その最も単純な符号化である UCS-4 にも (32 ビット・ワードの列として) 同じ問題がある。

UnicodeUCSUTF-8 符号化にはこれらの問題がないので、Unix 形式の OS 上で Unicode 文字集合を使用するための一般的な方法となっている。

性質


UTF-8 符号化は以下のような素晴しい性質を備えている:
* UCS 文字のうち 0x00000000 から 0x0000007f まで (古典的な US-ASCII の文字) は (ASCII との互換性のために) 単純に 0x00 から 0x7f のバイトに 符号化する。これは 7 ビット ASCII 文字のみを含むファイルや文字列に 関しては、 ASCIIUTF-8 で同じ符号化を行なうことを意味する。
* 0x7f より大きいのすべての UCS 文字は、 0x80 から 0xfd までの範囲のバイトのみを含む 多バイト文字列に符号化される。 したがって文字列に ASCII バイトが含まれることがなく、’\0’ や ’/’ の問題は発生しない。
* UCS-4 文字列では辞書的ソートの順序が保たれる。
* 2^31 ビットのすべての UCS コード が UTF-8 を使用して符号化できる。
* UTF-8 符号化では 0xfe と 0xff のバイトは絶対に使用しない。
* ASCII でない UCS 文字の多バイト列の最初のバイトは、 常に 0xc0 から 0xfd の範囲で表現され、 その文字が何バイトで構成されているかを示す。 多バイト列の残りの部分のバイトは、それぞれ 0x80 から 0xbf の範囲にある。 これにより同期が容易になり、ステートレスな符号化が可能になり、 バイトの紛失に対して堅固になる。
* UTF-8 を使用した UCS 文字の符号化は最大 6 バイトの長さになる。 しかし、 Unicode 規格では 0x10ffff より先の文字を指定しないので、Unicode 文字は UTF-8 では 4 バイトまでにしかならない。

符号化


以下のバイト列が文字の表現に使用される。 どのバイト列を使用するかは文字の UCS コード番号に依存する:
0x00000000 - 0x0000007F:
 0xxxxxxx
0x00000080 - 0x000007FF:
 110xxxxx 10xxxxxx
0x00000800 - 0x0000FFFF:
 1110xxxx 10xxxxxx 10xxxxxx
0x00010000 - 0x001FFFFF:
 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
0x00200000 - 0x03FFFFFF:
 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
0x04000000 - 0x7FFFFFFF:
 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
xxx ビットの部分には 2 進数で表わした文字コードのビット部分が対応する。 その文字を表現するのに最も短いバイト列のみが使用できる。

0xd800-0xdfff (UTF-16 サロゲート) や 0xfffe, 0xffff (UCS の non-character) という UCS コードの値は、 UTF-8 に準拠したストリームに入れるべきではない。


Unicode 文字の 0xa9 = 1010 1001 (コピーライト・マーク) は UTF-8 で符号化すると

11000010 10101001 = 0xc2 0xa9

になる。

0x2260 = 0010 0010 0110 0000 (不等号) は

11100010 10001001 10100000 = 0xe2 0x89 0xa0

になる。

アプリケーションにおける注意


ユーザーはアプリケーションの UTF-8 サポートを有効にするために、以下のようにして UTF-8 ロケールを選択しなければならない。

export LANG=en_GB.UTF-8

使用されている文字符号化を分かっていなければならない アプリケーションソフトウェアは、 以下のようにして常にロケールを設定すべきである。

setlocale(LC_CTYPE, "")

また UTF-8 ロケールが選択されていて、プレーンテキストの標準入出力・端末間通信・ プレーンテキストファイルの内容・ファイル名・環境変数が UTF-8 で符号化されているかをチェックするために、 プログラマーは以下のような式を試すことができる。

strcmp(nl_langinfo(CODESET), "UTF-8") == 0

US-ASCIIISO 8859 といったシングルバイトの符号化が習慣になっているプログラマーは、 これまでの 2 つの仮定が UTF-8 ロケールにおいては最早有効ではなくなったことを知っておくべきだ。 1 番目の変更点は、1 バイトが必ずしも 1 つの文字に対応しないという点である。 2 番目の変更点は、最近の端末エミュレータは UTF-8 モードにおいて中国語・日本語・韓国朝鮮語の 全角文字 やスペースが入らない (non-spacing) 合成文字 (combining characters) に対応しているので、 ASCII のときのように 1 文字出力した後で カーソルを必ずしも 1 つだけ進めるわけではないという点である。 今日では、文字やカーソルの位置を数えるのに mbsrtowcs(3)wcswidth(3) といったライブラリ関数を使うべきである。

(VT100 端末などで使われる) ISO 2022 符号化形式から UTF-8 へ切替える公式なエスケープシーケンスは ESC % G ("\x1b%G") である。 これに対応する UTF-8 から ISO 2022 へのリターンシーケンスは ESC % @ ("\x1b%@") である。 (G0 セットと G1 セットを切替えるといった) その他の ISO 2022 シーケンスは、UTF-8 モードでは使えない。

予知できる将来では、POSIX システム上の一般的な文字符号化の全てのレベルで UTF-8ASCIIISO 8859 を置き換え、プレーンテキストを扱う非常に優れた環境が作られることが期待できる。

セキュリティ


UnicodeUCS の規格では、 UTF-8 の生成者はできるだけ短い形式を用いるよう要求している。 例えば、先頭バイトが 0xc0 であるような 2 バイト列を 生成するのは準拠しているとはいえない。 Unicode 3.1 では、規格に準拠するプログラムは 最短の表現形式ではない入力を受け付けない、という要求事項が追加された。 これはセキュリティ上の理由による。 ユーザー入力がセキュリティ上の危険に対しチェックされる場合、 プログラムは ASCII 版の "/../" や ";" や "NUL" だけをチェックし、 最短に符号化されてないこれらの文字を見過ごしてしまうかもしれないからである。 なぜなら、最短ではない UTF-8 符号化では、これらの文字を表現するような様々な ASCII 以外の形式が存在するためである。

準拠


ISO/IEC 10646-1:2000, Unicode 3.1, RFC 2279, Plan 9.

関連項目


nl_langinfo(3), setlocale(3), charsets(7), unicode(7)

openSUSE Logo

コンテンツ