UTF-8ではUnicodeコードポイント値を次のようにエンコードする.
範囲 | ビットパターン | 第1バイト | 第2バイト | 第3バイト | 第4バイト |
---|---|---|---|---|---|
0000-007F |
0000 0000 0xxx xxxx |
0xxx xxxx |
|||
0080-07FF |
0000 0yyy yyxx xxxx |
110y yyyy |
10xx xxxx |
||
0800-FFFF |
zzzz yyyy yyxx xxxx |
1110 zzzz |
10yy yyyy |
10xx xxxx |
|
サロゲート(Unicodeスカラ値000p pppp rrrr rrrr cccc cccc ,ただしppppp=qqqq+1 )
|
|||||
D800-DBFF |
1101 10qq qqrr rrrr |
1111 0ppp |
10pp rrrr |
10rr rrcc |
10cc cccc |
DC00-DFFF |
1101 11rr cccc cccc |
10…
ではじまり,第1バイトのビットパターンとは重ならないようにしてある.
この工夫により,もしも伝送誤りが起こったりした場合でも,その誤りの影響が1文字の中に収まるようになっている.
ストリームを読み進めると数バイト先には10
以外ののパターンがきているはずで,底が次の文字の先頭バイトだとわかる.
0
ではじまっていたら→ASCII範囲内の文字で1バイトで表される文字10
ではじまっていたら→マルチバイト文字の第2バイト〜第4バイトのどれか110
ではじまってたら→2バイトの先頭文字1110
ではじまってたら→3バイトの文字の先頭文字11110
ではじまってたら→サロゲートペアで4バイトの文字00001≦ppppp≦11111
となり,第ppppp
面をそのまま使うと1ビットもったいない.
そこで,qqqq = ppppp - 1
と1ビット減らして,第qqqq+1
面・第rrrrrrrr
区・第cccccccc
点と読みかえたのち
110110qq qqrrrrrr 110111rr cccccccc
とエンコードする
(qqqq
に変換する手順を入れないと2×2バイトでは足りなくなる→詳細はサロゲートを参照).
しかし,UTF-8ではppppp→qqqq+1
の変換はせず,そのまま5ビットのppppp
を使ってエンコードする
(UTF-8では5ビットのまま扱ってもビット数が足りるため).
ある文字をUTF-8でエンコードしたときに何バイトになるかは,次のように導出できる.
0xxx xxxx
0111 1111 = 0x7F
0x0000
〜0x007F
(ASCII範囲内…あたりまえだけども)110x xxxx 10xx xxxx
0111 1111 1111 = 0x7FF
0x0080
〜0x07FF
1110 xxxx 10xx xxxx 10xx xxxx
0xFFFF
------------------------------------------------------------------------------- バイト数 UTF-8ビットパターン 有効ビット数と最大値 範囲 ------------------------------------------------------------------------------- 7 bits 7 bits <------> <------> 1バイト 0xxx xxxx 0111 1111 0000〜007F 7 F ASCII範囲 5 bits + 6 bits 11 bits <----> <-----> <-----------> 2バイト 110x xxxx 10xx xxxx 0111 1111 1111 0080〜07FF 7 F F 4 bits + 6 bits + 6 bits 16 bits <--> <-----> <-----> <-----------------> 3バイト 1110 xxxx 10xx xxxx 10xx xxxx 1111 1111 1111 1111 0800〜FFFF F F F F UCS-2範囲 -------------------------------------------------------------------------------