名前

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

説明

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

性質

UTF-8 符号化は以下のような素晴しい性質を備えている:
*
UCS 文字のうち 0x00000000 から 0x0000007f まで (古典的な US-ASCII の文字) は (ASCII との互換性のために) 単純に 0x00 から 0x7f のバイトに符号化する。 これは 7 ビット ASCII 文字のみを含むファイルや文字列に関しては、 ASCII と UTF-8 で同じ符号化を行なうことを意味する。
*
0x7f より大きいのすべての UCS 文字は、 0x80 から 0xfd までの範囲のバイトのみを含む 多バイト文字列に符号化される。 したがって文字列に ASCII バイトが含まれることがなく、'\0' や '/' の問題は発生しない。
*
UCS-4 文字列では辞書的ソートの順序が保たれる。
*
2^31 ビットのすべての UCS コード が UTF-8 を使用して符号化できる。
*
UTF-8 符号化ではバイト 0xc0, 0xc1, 0xfe, 0xff が使用されることはない。
*
ASCII でない UCS 文字の多バイト列の最初のバイトは、 常に 0xc2 から 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 10 xxxxxx
0x04000000 - 0x7FFFFFFF:
1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10 xxxxxx 10xxxxxx
xxx ビットの部分には 2 進数表現の文字コードのビット部分が対応する。 2 進数表では最上位ビット (MSB) が最初に置かれる (big-endian)。その文字を表現するのに最も短いバイト列のみが使用できる。
0xd800–0xdfff (UTF-16 サロゲート) や 0xfffe, 0xffff (UCS の noncharacter) という UCS コードの値は、 UTF-8 に準拠したストリームに入れるべきではない。 RFC 3629 では U+10FFFF より上のコードポイントは使用すべきではないとされている。これにより、文字は 4 バイト以内に限定される。

Unicode 文字の 0xa9 = 1010 1001 (コピーライトマーク) は UTF-8 で符号化すると 以下のようになる。
11000010 10101001 = 0xc2 0xa9
0x2260 = 0010 0010 0110 0000 (不等号) は以下の通り。
11100010 10001001 10100000 = 0xe2 0x89 0xa0

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

ユーザーはアプリケーションの UTF-8 サポートを有効にするために、
export LANG=en_GB.UTF-8
のようにして UTF-8 ロケールを選択しなければならない。
使用されている文字符号化を分かっていなければならない アプリケーションソフトウェアは、 以下のようにして常にロケールを設定すべきである。
setlocale(LC_CTYPE, "")
また、プログラマーは
strcmp(nl_langinfo(CODESET), "UTF-8") == 0
という式を評価することで、 UTF-8 ロケールが選択されていて、プレーンテキストの標準入出力・端末間通信・ プレーンテキストファイルの内容・ファイル名・環境変数が UTF-8 で符号化されているかをチェックすることができる。
US-ASCII や ISO 8859 といったシングルバイトの符号化が習慣になっているプログラマーは、 これまでの 2 つの仮定が UTF-8 ロケールにおいては最早有効ではなくなったことを知っておくべきだ。 1 番目の変更点は、1 バイトが必ずしも 1 つの文字に対応しないという点である。 2 番目の変更点は、最近の端末エミュレータは UTF-8 モードにおいて中国語・日本語・韓国朝鮮語の 全角文字やスペースが入らない (nonspacing) 合成文字 (combining characters) に対応しているので、 ASCII のときのように 1 文字出力した後で カーソルを必ずしも 1 つだけ進めるわけではないという点である。 今日では、文字やカーソルの位置を数えるのに mbsrtowcs(3)wcswidth(3) といったライブラリ関数を使うべきである。
(VT100 端末などで使われる) ISO 2022 符号化形式から UTF-8 へ切替える公式なエスケープシーケンスは ESC % G (" これに対応する UTF-8 から ISO 2022 へのリターンシーケンスは ESC % @ (" (G0 セットと G1 セットを切替えるといった) その他の ISO 2022 シーケンスは、UTF-8 モードでは使えない。

セキュリティ

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

標準

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

関連項目

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

この文書について

この man ページは Linux man-pages プロジェクトのリリース 5.10 の一部である。プロジェクトの説明とバグ報告に関する情報は https://www.kernel.org/doc/man-pages/ に書かれている。

Recommended readings

Pages related to utf-8 you should read also: