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 = 0x7F0x0000〜0x007F(ASCII範囲内…あたりまえだけども)110x xxxx 10xx xxxx
0111 1111 1111 = 0x7FF0x0080〜0x07FF1110 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範囲
-------------------------------------------------------------------------------