先に要点
- UTF-8 は、文字をコンピュータの中でどう並べて保存・送受信するかを決める文字コードの一種 です。Unicode という文字の土台を、実際のバイト列にする「表し方」にあたります。
- Web、JSON、HTML、CSS、JavaScript、API、各種テキストファイルで広く使われており、今は「まず UTF-8 を選ぶ」が基本 です。
- ただし UTF-8 を選んでも、保存・伝達・読み取りの3つがそろわないと文字化けは起きます。MySQL の
utf8で絵文字が消える、BOM なし UTF-8 を Excel が Shift_JIS と誤判定する、といった事故が代表例です。 - 初心者向けに一言で言うと、UTF-8 は「文字化けしにくく、いろいろな文字を一緒に扱いやすい、今の標準寄りの文字コード」 です。
「UTF-8 ってよく見るけど、結局何?」「文字コードって何が違うの?」「Shift_JIS とどう違うの?」というのは、最初につまずきやすいところです。
でもここを雑に理解すると、CSV、Excel、Web、メール、DB で同じような文字化けを何度も踏みます。
この記事では、UTF-8 とは何かを、文字コードの基本、Unicode との関係、なぜ今よく使われるのか の順で整理し、最後に 実際に踏みやすい失敗を「現象 → 原因 → 確認 → 回避」の形で2件 載せます。
前に公開した 文字化けって何?防止方法、復元方法は? や CSVをExcelで開くと文字化けするのはなぜか の土台として読める形にしています。
そもそも文字コードとは何か
コンピュータは、文字をそのまま理解しているわけではありません。
内部では、文字は最終的にバイト列として保存されます。
たとえば人間には「あ」も「A」も「😊」も文字として見えますが、コンピュータの中では
- どの文字を
- どんなルールで
- 何バイトで表すか
を決める必要があります。
この「文字をバイト列にするルール」が文字コードです。実際にバイトを覗いてみると、ルールの違いがそのまま見えます。たとえば「あ」1文字を UTF-8 と Shift_JIS で書き出して16進数で見ると、次のように別のバイト列になります。
$ printf 'あ' | iconv -f UTF-8 -t UTF-8 | xxd
00000000: e381 82 ...
$ printf 'あ' | iconv -f UTF-8 -t SHIFT-JIS | xxd
00000000: 82a0 ..
UTF-8 では e3 81 82 の3バイト、Shift_JIS では 82 a0 の2バイトです。同じ「あ」でも、どのルールで保存したかでバイト列が違う。だから保存したルールと読むルールがずれると、化けるわけです。
UTF-8とは何か
UTF-8 は、その文字コードのひとつです。
もっと正確に言うと、Unicode の文字をバイト列へ変換する方法のひとつ です。
ここで大事なのは、UTF-8 自体が「文字の一覧」ではなく、文字を保存・送信するための表し方 だという点です。
初心者向けにざっくり言うなら、
- Unicode … どんな文字があるかをまとめた大きな土台
- UTF-8 … その文字を実際にどうバイトで表すかの方法
という理解でかなり十分です。
Unicodeとの関係
ここは混ざりやすいので、図ではなく言葉で分けておくと楽です。
Unicode(土台)
世界中の文字に通し番号(コードポイント)を割り当てる仕組み。たとえば「あ」は U+3042、「😊」は U+1F60A。どんな文字が存在するかを決める「設計図」にあたります。
UTF-8(表し方)
そのコードポイントを実際のバイト列に変換する方式。U+3042 を e3 81 82 の3バイトにする、といった「実装」にあたります。UTF-16 や UTF-32 も同じ土台を別のバイト列にする兄弟です。
つまり、Unicode が「文字の土台」、UTF-8 が「その土台を実際に保存する方法」です。ここを混ぜて「UTF-8 = 文字の種類」と思うと、後で MySQL の utf8/utf8mb4 のような落とし穴で混乱します。
なぜ UTF-8 がよく使われるのか
1. 日本語も英語も同じ土台で扱いやすい
昔は、英語圏は英語圏、日本語圏は日本語圏で別の文字コードを使うことが多く、そこから文字化けが起きやすくなっていました。
UTF-8 は Unicode を前提にしているので、日本語と英語と記号と絵文字を同じ土台で扱いやすいです。今の Web や API で UTF-8 が強いのは、この「混在に強い」ところが大きいです。
2. ASCII と相性がよい
UTF-8 では、英数字や基本記号の範囲(U+0000〜U+007F)が ASCII と完全に同じ1バイトになります。
つまり英語だけのテキストなら、昔ながらの ASCII 系とそのままつながります。この性質のおかげで、英語中心のプログラム・設定ファイル・HTML・JSON と相性がよく、広く普及しました。
3. Web の標準寄りだから
WHATWG の Encoding Standard や MDN でも、今の Web では UTF-8 が基本です。
HTML の <meta charset="utf-8"> や HTTP の charset=utf-8 を見かけるのはそのためです。実務では HTML / CSS / JavaScript / JSON / API レスポンス / Markdown / 設定ファイルの多くで、まず UTF-8 を使う前提になっています。
UTF-8 の「8」って何?
UTF-8 の「8」は、8ビット(1バイト)単位で並べる方式 という名前の一部です。
ただし「1文字 = 8ビット固定」という意味ではありません。ここは誤解しやすいところです。
UTF-8 では、文字によって使うバイト数が変わります。下の表が目安です(容量の見積もりにも使えます)。
| 文字の種類 | UTF-8 のバイト数 | 例 |
|---|---|---|
| ASCII(英数字・基本記号) | 1バイト | A, 1, @ |
| ラテン拡張・ギリシャ文字など | 2バイト | é, ü, α |
| 日本語・中国語・韓国語 | 3バイト | あ, 漢, 한 |
| 絵文字・一部の補助文字・数学記号 | 4バイト | 😊, 𠮷(つちよし) |
つまり UTF-8 は 可変長の文字コード です。初心者向けには「英語は軽く、日本語や絵文字は少し重い」くらいの感覚で十分ですが、この 「絵文字や一部の漢字は4バイト」 という事実が、後で出てくる MySQL の事故の伏線になります。
Shift_JIS と何が違うのか
日本語圏でよく比べられるのが Shift_JIS です。Shift_JIS は、日本語 Windows や古い業務システム、Excel 前提の CSV 運用などで今でも出てくることがあります。主な違いを表にします。
| 観点 | UTF-8 | Shift_JIS |
|---|---|---|
| 扱える文字 | 世界中の文字・絵文字まで | 主に日本語・英数字(扱えない文字がある) |
| Web / API | 標準寄り。JSON・HTML と相性がよい | 非推奨。多言語・記号で不利 |
| 日本語1文字のバイト数 | 3バイト | 2バイト |
| 古い日本語環境 | 環境次第で要設定 | なじみが深く、相性がよいことがある |
だから今の基本は UTF-8 ですが、業務の相手が誰か(古い社内システム、取引先の指定フォーマットなど)によって Shift_JIS がまだ残ることがあります。
BOM とはどう関係するのか
UTF-8 を調べると、よく BOM が出てきます。BOM はファイル先頭に付く目印で、UTF-8 の場合は EF BB BF の3バイトです。
UTF-8 では BOM は必須ではありません。むしろ Web やプログラム間では BOM なしが基本です。
ただし、相手のツールが文字コードを自動判定する場面では、この目印があるかどうかで結果が変わります。特に Excel の CSV では、Microsoft 公式でも UTF-8 CSV は BOM 付きなら通常どおり開ける と案内されています。なので、UTF-8 と BOM は別物ですが、実務では一緒に出てきやすいです。
実際に踏む失敗例と切り分け
ここからが本題です。「UTF-8 にしたのに化けた」は、たいてい 保存・伝達・読み取りのどこかがずれている だけです。代表的な2件を、現象から回避まで追います。
失敗例1: MySQL の utf8 で絵文字が消える/保存できない
これは utf8 と utf8mb4 の取り違えで起きる、非常に多い事故です。
現象
ユーザーが投稿した「ありがとう😊」を保存すると、絵文字だけ消えて「ありがとう」になる。あるいは保存自体が ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x98\x8A' for column 'body' で失敗する。
原因
MySQL の utf8 は歴史的事情で 1文字3バイトまでしか扱えない別物(正式名 utf8mb3)。絵文字は4バイトなので入りません。本物の UTF-8 は utf8mb4 です。
確認手順は次のとおりです。化ける文字を入れている列の文字コードを直接見ます。
mysql> SHOW CREATE TABLE posts\G
*************************** 1. row ***************************
Table: posts
Create Table: CREATE TABLE `posts` (
`body` text CHARACTER SET utf8mb3 ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
ここで utf8 / utf8mb3 と出たら原因確定です(utf8mb4 なら別の問題)。接続側のずれも疑うなら次も確認します。
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| character_set_client | utf8mb3 | <- ここが utf8/utf8mb3 だと送信時点で削れる
| character_set_connection | utf8mb3 |
+--------------------------+---------+
回避は、テーブル・列・接続のすべてを utf8mb4 にそろえる ことです。列の変換は次のように行います(本番では事前バックアップを取ってから)。
ポイントは「列だけ直しても接続が utf8 なら直らない」点です。3か所(列・テーブル・接続)を全部見るのが切り分けの近道です。MySQL では新規構築なら最初から utf8mb4 一択と覚えてよいです。
失敗例2: BOM なし UTF-8 の CSV を Excel が文字化けさせる
こちらは utf8mb4 の話とは逆に、「正しく UTF-8 で保存したのに化ける」典型です。
現象
プログラムが正しく UTF-8 で書き出した CSV を、Windows 版 Excel でダブルクリックして開くと、日本語が「縺ゅj縺後→縺・」のような文字化けになる。メモ帳や VS Code で開けば正常に読める。
原因
日本語版 Excel は、CSV をダブルクリックで開くと先頭に BOM がない限り Shift_JIS(ANSI)だと推測して読む。ファイルは UTF-8 なのに、読み手が別コードで解釈しているための文字化けです。ファイル自体は壊れていません。
確認手順は、ファイル先頭のバイトを見るのが確実です。
$ head -c 3 export.csv | xxd
00000000: e3 81 82 ...
# -> EF BB BF で始まっていない = BOM なし。Excel が Shift_JIS と誤判定する条件に合致
先頭が EF BB BF なら BOM 付き、いきなり本文のバイト(上の例では「あ」の e3 81 82)なら BOM なしです。回避は次のどちらかです。
回避A: 出力に BOM を付ける
Excel 配布用と割り切るなら、書き出し時に BOM を付ける。Python なら open(path, "w", encoding="utf-8-sig") にするだけで先頭に EF BB BF が入り、ダブルクリックで正しく開ける。
回避B: 読み手側で取り込む
ファイルを変えられないなら、Excel の「データ → テキストまたは CSV から」で取り込み、ウィザードで文字コードに「65001: Unicode (UTF-8)」を指定する。ダブルクリックは使わない。
注意点として、BOM は Excel には効きますが、Web やプログラム間連携では BOM が逆に邪魔になる(先頭に見えない文字が混ざる)ことがあります。だから「人間が Excel で開く用は BOM 付き、システム連携用は BOM なし」と用途で分けるのが実務的な落としどころです。
UTF-8 なら絶対に文字化けしないのか
ここまでで分かるとおり、答えは「しない、とは言えない」です。
UTF-8 自体は強いですが、読む側が UTF-8 として読まないと文字化けは起きます。化けたときは、次の3点のどこがずれているかを順に潰します。
- 保存(エンコード): 本当に UTF-8 で書けているか(
utf8mb4かどうかも含む) - 伝達(宣言): HTTP の
charset=utf-8、HTML の<meta charset="utf-8">、CSV の BOM 有無など、相手に正しく伝わっているか - 読み取り(デコード): 受け手(ブラウザ、Excel、DB 接続)が UTF-8 として読んでいるか
「UTF-8 で保存する・UTF-8 と伝える・UTF-8 として読む」の3つをそろえる。これがすべての文字化け切り分けの軸になります。
初心者向けにどう理解すればいい?
実務で困らない理解としては、次の順で十分です。
- 文字コードは「文字をバイト列にするルール」。同じ「あ」でも UTF-8 と Shift_JIS でバイト列が違う。
- UTF-8 は今いちばんよく使うルール。Web・API・テキストファイルでは、まず UTF-8 を疑う・選ぶ・そろえる。
- UTF-8 でも読み方がズレれば文字化けする。保存・伝達・読み取りの3点を見る。
- MySQL の utf8 と Excel の CSV は例外的な落とし穴。前者は
utf8mb4、後者は BOM か取り込み手順を意識する。
実務で最初にやるとよいこと
もし自分でシステムやファイル出力を触るなら、最初に次を統一するとかなり楽です。
- ソースコードは UTF-8(BOM なし)
- HTML は
<meta charset="utf-8"> - HTTP レスポンスは
Content-Typeにcharset=utf-8 - JSON は UTF-8(BOM なし)
- DB(MySQL)は
utf8mb4で統一 - CSV は利用先に応じて、Excel 配布用は UTF-8+BOM、システム連携用は BOM なし
この土台があるだけで、文字化けトラブルはかなり減ります。
UTF-8に関するよくある質問
Q. UTF-8 と Unicode は同じですか?
A. 違います。Unicode は「文字に番号(コードポイント)を割り当てる仕組み」、UTF-8 は「その番号をバイト列に変換する方式の1つ」です。設計図と実装のような関係で、UTF-16・UTF-32 も同じ Unicode を別のバイト列にする兄弟にあたります。
Q. UTF-8 の「8」の意味は?
A. 「8ビット(1バイト)単位で並べる可変長エンコード」という意味です。1文字8ビット固定ではなく、英数字は1バイト、日本語は3バイト、絵文字は4バイト、と内容に応じて長さが変わります。
Q. UTF-16、UTF-32 との違いは?
A. UTF-16 は1文字2バイトまたは4バイト(Windows や Java の内部表現で使われる)、UTF-32 は1文字4バイト固定(処理は単純だが容量が大きい)です。Web では UTF-8 が圧倒的標準で、ファイルやネットワークでわざわざ UTF-16/32 を選ぶ場面はまれです。
Q. MySQL の utf8 と utf8mb4 の違いは?
A. MySQL の utf8(正式名 utf8mb3)は1文字3バイトまでで、絵文字や一部の漢字(4バイト)が保存できません。utf8mb4 が本物の UTF-8 です。絵文字が消える・Incorrect string value エラーが出る、という症状はほぼこれが原因です。新規構築なら utf8mb4 一択です。
Q. UTF-8 の CSV を Excel で開くと化けるのはなぜ?
A. 日本語版 Excel は、CSV をダブルクリックで開くと BOM がない限り Shift_JIS だと推測して読むためです。回避は (A) 書き出し時に BOM を付ける(Python なら encoding="utf-8-sig")、(B)「データ → テキストまたは CSV から」で 65001:UTF-8 を指定して取り込む、のどちらかです。
Q. 言語別の1文字あたりのバイト数は?
A. ASCII(英数字)= 1バイト、ラテン拡張など = 2バイト、日本語/中国語/韓国語 = 3バイト、絵文字/補助文字/数学記号 = 4バイトが目安です。テキストの容量見積もりや、DB の列長設計の参考になります。
Q. UTF-8 でも文字化けする理由は?
A. 送信側 UTF-8 なのに受信側が Shift_JIS で解釈する、Content-Type に charset 指定がない、BOM の有無で自動判定が外れる、DB の接続文字コードだけ別になっている、などです。「UTF-8 = 万能」ではなく、保存・伝達・読み取りをそろえる必要がある、という認識が大事です。
Q. プログラミング言語の UTF-8 対応は?
A. 現代の主要言語(Python 3、Node.js、Java、Go、Rust、PHP 7+、Ruby 1.9+)は基本的に UTF-8 がデフォルトです。古い VBA や C(明示的な処理が必要)では注意が要ります。
まとめ
UTF-8 は、Unicode の文字を保存・送信するための代表的な文字コード です。
日本語、英語、記号、絵文字まで広く扱え、今の Web やテキスト処理では基本の選択肢になっています。
初心者向けには、
- 文字コードは文字をバイト列にするルール
- UTF-8 は今いちばんよく使うルール
- ただし保存・送信・表示がそろわないと文字化けする
この3つを押さえれば十分です。実務では「とりあえず UTF-8」がかなり強いですが、MySQL の utf8mb4 と Excel CSV の BOM という2つの例外を知っているかどうかで、踏むトラブルの数がはっきり変わります。「相手がどう保存し、どう読むか」まで見るのがいちばん大事です。
この記事と一緒に読みたい
参考リンク
- WHATWG: Encoding Standard
- MDN: Content-Type header
- MySQL: The utf8mb4 Character Set
- Microsoft: Open a UTF-8 CSV file in Excel without mis-conversion