文字コードとバイトの違い|UTF-8・UTF-16・コードポイントを実例で理解
公開日:2026年10月12日 更新日:2026年10月13日 運営:シルギア(アナライズギア株式会社) 対象ツール:文字コード・バイト列ビューア
「文字」は画面では1つの記号に見えますが、コンピュータの内部ではすべて数値と、その数値を保存・送信するためのバイト列に置き換えられています。本記事では、本ツール「文字コード・バイト列ビューア」で実際に確かめられる範囲に沿って、文字コードとバイトの違い、UnicodeとUTF-8/UTF-16、コードポイントやサロゲートペアといった概念を、具体的な数値とともに整理します。文字数とバイト数がなぜずれるのか、絵文字がなぜ2文字と数えられることがあるのかも、手を動かしながら理解できます。
文字コードとバイトは別物
私たちが入力した文字は、まずコードポイントという「番号」に対応づけられ、次にそれを実際のデータにするためバイト列へ符号化されます。つまり「文字→番号→バイト」という2段階の変換が起きています。文字コード(コードポイント)は各文字に割り当てられた抽象的な番号で、「A」なら U+0041 という値そのものを指します。一方バイトは、その番号を保存・通信できる形にした結果です。同じ番号でも、後述する符号化方式が違えば出てくるバイト列は変わります。この2つを混同し「1文字=1バイト」と思い込むと、文字化けやバイト数の見積もり違いが生まれます。
Unicodeと符号化方式 — UTF-8とUTF-16
世界中の文字を1つの体系で扱うために作られたのがUnicodeで、各文字に一意のコードポイントを与えます。その番号を実際のバイト列に落とし込む方式が符号化方式で、代表格が UTF-8 と UTF-16 です。
- UTF-8:ASCII文字(A〜Zや数字)を1バイト、日本語などを3バイト前後で表す可変長方式。先頭128個がASCIIと一致し、Webやファイルの事実上の標準です。
- UTF-16:多くの文字を2バイト(1コード単位)で表し、絵文字などは4バイト(2コード単位)になります。JavaScriptの文字列内部はこのUTF-16が基礎です。
同じ「あ」でも、UTF-8では3バイト、UTF-16では2バイトと、方式によってバイト数も並びも変わる点が要です。
コードポイント(U+XXXX)とサロゲートペア
コードポイントは U+ に続けて16進数で書きます。「A」は U+0041、「あ」は U+3042 です。UTF-16は U+FFFF までを1つのコード単位で表しますが、それを超える文字(多くの絵文字など)はサロゲートペアと呼ばれる2つのコード単位の組みで表現します。見た目は1文字でも、単純な文字列長(str.length)では2と数えられてしまうのはこのためです。本ツールは codePointAt などで文字列を走査し、サロゲートペアを正しく1つの文字(1コードポイント)として扱うため、絵文字も過不足なく表示します。
実例で確かめる — A・あ・🍣
言葉だけでは掴みにくいので、本ツールに次の文字を入力して自分の目で確かめてみてください。
- A:U+0041。UTF-8は 41 の1バイト、UTF-16も1コード単位(0041)。
- あ:U+3042。UTF-8は E3 81 82 の3バイト、UTF-16は1コード単位(3042)。
- 🍣(寿司):U+1F363。UTF-8は F0 9F 8D A3 の4バイト、UTF-16は D83C DF63 の2コード単位(サロゲートペア)。
同じ「1文字」でも、英字は1バイト、ひらがなは3バイト、絵文字は4バイトと大きく差が出ます。この差こそが、文字数とバイト数がずれる正体です。
文字数とバイト数がずれる理由とパーセントエンコード
文字の数え方には「見た目の文字(書記素)」「コードポイント」「UTF-16コード単位」の3通りがあり、絵文字や合成文字ではこれらが食い違います。本ツールの「文字数」はコードポイント数で、UTF-8バイト長やUTF-16コード単位数とは別に併記しています。だから絵文字1個でも、文字数1・UTF-8で4バイト・UTF-16で2コード単位、と数え方ごとに値が変わるのです。
URLに日本語や記号を安全に埋め込むときに使うパーセントエンコードも、この仕組みの延長です。encodeURIComponent は各文字のUTF-8バイトを %XX の形式で並べるため、「あ」は %E3%81%82 となり、内訳表のUTF-8バイト列とそのまま対応します。バイト列を理解していれば、パーセントエンコードの結果も暗号ではなく読める文字列に見えてきます。
なぜShift-JISは扱えないのか、そして使いどころ
本ツールはブラウザ標準の TextEncoder でバイト列を求めますが、この標準APIはUTF-8への符号化のみに対応し、Shift-JIS(cp932)などのレガシー符号化には対応していません。外部ライブラリやサーバー送信を使わない完全静的の方針のため、扱う対象をUTF-8とUTF-16に絞っています。こうした知識は、次のような実務の場面で役立ちます。
- DB設計:カラム長がバイト単位か文字単位かで、実際に入る文字数が変わります。UTF-8バイト長の見積もりに使えます。
- API・データ連携:想定外のバイト列が出る文字化けの原因切り分けに。
- 文字数制限:SNSやフォームで絵文字が2文字分と数えられてしまう不具合の確認に。
入力した文字はすべて端末内で処理され、外部には送信されません。気になる文字や記号、絵文字を貼り付けて、その正体を数値で確かめてみてください。
改行やスペースも1文字・数バイトを持つ
バイト数を見積もるときに忘れやすいのが、目に見えない文字です。半角スペースはUTF-8で1バイト(20)、改行はLFが1バイト(0A)ですが、Windowsで使われるCRLFは0D 0Aの2バイトになります。同じ本文でも、改行コードがLFかCRLFかでテキスト全体のバイト数は変わります。長さ制限のある項目や通信量を厳密に見積もるときは、こうした制御文字の分も数えに入っているか確認しておくと安心です。
「全角2バイト・半角1バイト」はUTF-8では通じない
かつてのShift-JISの常識「全角は2バイト、半角は1バイト」は、UTF-8では当てはまりません。UTF-8では半角の英数字は1バイトですが、ひらがな・漢字・全角記号の多くは3バイトになります。「全角だから2バイト」という感覚でDBのカラム長やバイト制限を見積もると、実際には足りなくなってしまいます。実際のバイト数は符号化方式によって変わるので、思い込みに頼らず本ツールで確かめるのが確実です。
絵文字の結合(ZWJ・肌色・国旗)でさらにずれる
一部の絵文字は、複数のコードポイントをゼロ幅接合子(ZWJ)という見えない文字でつなぎ、1つの見た目を作っています。家族を表す絵文字や、肌の色のついた絵文字、国旗などがその例です。見た目は1文字でも、コードポイント数・UTF-16コード単位・UTF-8バイト数はいずれも増えます。SNSやフォームの文字数制限で、1文字のつもりが複数文字分として数えられてしまう——という不具合の典型的な原因がこれです。