FE EXAM

UTF-8(可変長エンコーディング)

Unicodeを1〜4バイトの可変長で符号化する、最も普及した文字エンコーディング

INTERACTIVE VISUALIZATION
先頭パターン
後続印(10)
文字データ
コードポイント
U+3042
10進
12354
UTF-8のバイト数
3 バイト
範囲: U+0800〜U+FFFF(日本語・記号等) / 入力全体: 3 バイト
文字を入力
先頭の1文字をUTF-8に符号化して表示します
サンプル(バイト数別)
UTF-8 バイト列の内訳
1バイト目0xE3先頭バイト(1110 で始まる = 全3バイト)
1
1
1
0
0
0
1
1
1110+0011
2バイト目0x81後続バイト(必ず 10 で始まる)
1
0
0
0
0
0
0
1
10+000001
3バイト目0x82後続バイト(必ず 10 で始まる)
1
0
0
0
0
0
1
0
10+000010
=バイト数を示す先頭の固定パターン、=後続バイトの目印「10」、=文字データそのものを表すビット。青の部分だけを順につなげるとコードポイントになります。
解説

📌
UTF-8とは

Unicode番号 → UTF-8のバイト列に変換U+3042E38182「あ」は3バイトになる

UTF-8=Unicode Transformation Format-8bit の略で、「Unicode(世界中の文字に番号を振った規格)」の文字番号を、実際のバイト列に変換する方式のひとつです。Unicodeはあくまで「あ=U+3042 番」のように番号を決めるだけの仕様で、その番号をどんなバイトの並びで保存・送信するかを決めるのがUTF-8です。

身近な例で言うと、住所を郵便で送るときの「封筒への書き方ルール」に近いです。住所(=Unicode番号)そのものは決まっていても、それを実際に紙にどう書いて運ぶか(=バイト列)にはルールが必要です。UTF-8はその「運び方のルール」の中で世界で最も広く使われているもので、Web(HTML)やほとんどのプログラムの標準になっています。

上のツールで文字を入力すると、その文字がUTF-8で何バイトになり、各バイトがどんなビットで構成されるかが表示されます。A・あ・😀のサンプルを切り替えて、バイト数が文字によって変わる様子を見てみてください。

🧩
1〜4バイト可変長の仕組み

UTF-8の特徴は「文字によって使うバイト数が変わる(可変長)」ことです。よく使う文字は少ないバイト数で、めったに使わない文字は多いバイト数で表します。これにより、英語の文章ならファイルサイズが小さく済みます。

バイト数コードポイント範囲ビットパターン
1U+0000〜007F0xxxxxxxA, 1, !
2U+0080〜07FF110xxxxx 10xxxxxxñ, é
3U+0800〜FFFF1110xxxx 10xxxxxx 10xxxxxxあ, 漢
4U+10000〜10FFFF11110xxx 10xxxxxx 10xxxxxx 10xxxxxx😀

バイト数を見分ける仕掛けは「先頭ビットのパターン」です。上のツールでも色分けして表示しています。
先頭バイトの最初の1の個数=そのバイト数を意味する(110なら2バイト、1110なら3バイト)
後続バイトは必ず 10 で始まる(文字の途中だと一目で分かる)
・残りの x の部分に、文字番号のビットを詰める

この仕組みのおかげでどこから読んでも文字の区切りが分かるのが大きな利点です。先頭が 0 なら1バイト文字、10 なら文字の途中、11 なら新しい文字の先頭、と機械的に判断できます。

💡
なぜ後続バイトは必ず「10」始まりなのか

先頭ビットを見るだけで「どこから読んでも」分かる0xxxxxxx1バイト文字の先頭11xxxxxx多バイト文字の先頭10xxxxxx後続バイト(文字の途中)「あ」の3バイトを先頭ビットだけで識別1110...先頭10...続き10...続きどの位置から読み始めても「10」=途中、「0」or「11」=先頭と判定できる

後続バイト(2バイト目以降)が必ず 10 で始まる理由は、「バイト列のどの位置から読み始めても、今読んでいるバイトが文字の先頭か途中かを一瞬で判定できる」ようにするためです。

ルールを整理すると以下の3種類だけです。
・先頭ビットが 0:1バイト文字(ASCII領域)の先頭
・先頭2ビットが 11:2〜4バイト文字の先頭バイト(1の個数でバイト数がわかる)
・先頭2ビットが 10後続バイト(文字の途中)

これを自己同期性(=どこから読んでも文字の区切りが分かる性質)と呼びます。たとえばファイルの途中から読み込んだとき、まず先頭ビットが 10 のバイトを読み飛ばし続ければ、必ず次の文字の先頭(0 または 11)に到達できます。この仕組みにより、通信エラーで数バイト欠けても次の文字から正常に復帰できるのです。

💡
文字コードの種類と文字化けの仕組み

方式特徴ASCII互換よく使う場面
UTF-8可変長(1〜4バイト)Web・Linux・macOS
Shift_JIS可変長(1〜2バイト)△(一部NG)古いWindowsソフト・CSV
UTF-16固定2 or 4バイト×Windows内部・Java
EUC-JP可変長(1〜3バイト)旧UNIX・メール

文字化けとは、ファイルを書いたときの文字コードと、読み込んだときの文字コードが違うために発生する「解釈の食い違い」です。バイト列そのものは正しく保存されているのに、違うルールで解読しようとするから文字が崩れます。

身近なたとえで言うと、モールス信号を送ったのに相手がアルファベットと聞き間違えたのと同じです。信号(バイト列)は正確に届いていても、解読ルール(文字コード)が違えば意味が変わります。

代表的な文字化けのパターンを2つ紹介します。
Shift_JISで書いたファイルをUTF-8として読む:日本語の箇所が「縺ゅ&縺薙″縺ゅ▲縺ヲ」のような全く違う文字になる。逆もまた然り
Shift_JISで「¥」記号がバックスラッシュになる:Shift_JISでは 0x5C が「¥」だが、ASCIIでは「\」。同じバイトなのに解釈が違う(完全なASCII互換でない例)

UTF-8が現在の標準になった理由は、ASCII互換・自己同期・世界中のすべての文字を一つの規格で扱えるという3つの利点を兼ね備えているからです。Webのページの宣言(<meta charset="UTF-8">)はこの文字コードをブラウザに伝えるためのもので、宣言がないと文字化けの原因になります。

🔗
ASCIIとの互換性

「A」は ASCII も UTF-8 も同じ 1 バイトASCII10000010x41UTF-8010000010x41(完全に一致)=

UTF-8がここまで普及した最大の理由が「ASCIIと完全な互換性がある」ことです。コードポイントが U+0000〜U+007F(=ASCIIの128文字)の場合、UTF-8では1バイトで表現され、その値はASCIIコードとまったく同じになります。

例えば「A」はASCIIで 0x41(10進65)。UTF-8でも先頭ビットが 0 の1バイト 01000001 = 0x41 です。つまり英数字だけの文章なら、ASCIIファイルとUTF-8ファイルは中身が1バイトも変わりません

この互換性により、次のような利点が生まれます。
既存のASCIIデータをそのままUTF-8として扱える(変換不要)
英数字中心の通信・保存ではサイズが増えない(1文字1バイトのまま)
日本語など多バイト文字の中にASCII記号が混ざってもズレない(後続バイトは必ず 10 始まりでASCII領域と被らない)

UTF-8の主な性質は「ASCIIと上位互換」「ASCII文字は1バイト」「日本語は3バイトが基本」です。固定長で全文字を同じバイト数にするUTF-16/32との違い(UTF-8は可変長)も合わせて理解しておくとよいでしょう。

関連コンテンツ