コンピューターサイエンス入門:理論編
UTF-8 のバイト長を返す
この回でやること
UTF-8の文字数とバイト数の違いを読み解き、保存先の長さ制限に収まるかを確かめます。
- 読む 約 7 分
- 最後にクイズ 1 問
「1文字1バイト」で見積もると、足りなくなる
入力欄を100文字までにしたい。保存先を100バイトで用意したら、ひらがな40文字で足りなくなりました。英語では収まったのに、日本語だと収まりません。
UTF-8では1文字のバイト数が一定ではありません。A は1バイト、あ は3バイトです。ひらがな40文字なら40 × 3 = 120バイトになります。文字が混ざる場合、全体の文字数に同じ数を掛けるだけでは求められません。
Python
print(len('あA')) # 2
print(len('あA'.encode('utf-8'))) # 4encode は文字列を指定した方式のバイト列へ変えます。上は文字の数、下はUTF-8にしたあとのバイト数です。ここでは1つのUnicodeの番号で表せる文字を扱います。
先頭のバイトが、続きの個数を示す
UTF-8は先頭バイトに長さの印を入れます。x は文字の番号を収めるビットです。
プレーンテキスト
0xxxxxxx 1バイト
110xxxxx 10xxxxxx 2バイト
1110xxxx 10xxxxxx 10xxxxxx 3バイト
11110xxx 10xxxxxx 10xxxxxx 10xxxxxx 4バイト先頭が 0 なら1バイトで終わり、110 なら続きが1個、1110 なら2個です。続きは 10 で始まるので、先頭と区別できます。不正な並びから元の文字を復元できるとは限りません。
ASCIIの英数字は1バイトの形と共通です。英数字だけなら、ASCIIとUTF-8で同じバイトの並びになります。
番号を収める場所にも限りがある
2バイト形式の x は5 + 6 = 11個、3バイト形式は4 + 6 + 6 = 16個です。あ の番号0x3042は12354で、2進数では14桁です。11ビットには収まらず、3バイト形式を使います。ひらがなや多くの漢字は3バイトですが、日本語でも例外はあります。
数え方を混ぜると、文字の途中で切れる
現場の話 データベースや通信の長さ制限には、文字数のものとバイト数のものがあります。入力欄の文字数だけでは、保存先に収まると判断できません。
3バイトの文字を途中で切ると、不完全なバイト列になります。読む側によってエラーや置換文字になります。制限の単位を確かめます。
例題で確かめる
文字列 猫AB をUTF-8で保存します。猫 は3バイト、A と B は各1バイトなので、3 + 1 + 1 = 5バイトです。3文字でも、4バイトまでの保存先には収まりません。文字数とバイト数を分けて考えます。