文字化け
テキストデータのエンコーディングとデコーディングの不一致により、本来の文字が意図しない記号や別の文字として表示される現象。
文字化け (mojibake) は、テキストを書き込んだときの文字コードと、読み出すときの文字コードが食い違うことで発生します。たとえば UTF-8 で保存された日本語テキストを Shift_JIS として開くと、「こんにちは」が「縺薙s縺ォ縺。縺ッ」のような意味不明な文字列に変わります。逆に Shift_JIS のファイルを UTF-8 で開くと、置換文字 � が大量に表示されるか、まったく別の漢字が並びます。
- 1. 書く側が UTF-8 で保存する 「こんにちは」の 5 文字は、UTF-8 では 1 文字 3 バイトずつ、合計 15 バイトのバイト列として保存されます。
- 「これは UTF-8 です」という約束が読む側に届かない
- 2. 読む側が Shift_JIS の区切りで読む 同じ 15 バイトを Shift_JIS の規則で 1〜2 バイトずつ区切り直すため、元の 5 文字とは違う位置で文字が組み立てられます。
- 別の文字コード表を引いて文字を決める
- 3. 画面には「縺薙s縺ォ縺。縺ッ」が出る 変わったのは表示だけで、元の 5 文字が別のデータに置き換わったわけではありません。読み出しに使う文字コードの指定が食い違っている状態です。
| 保存したときの文字コード | 読み出しに使った文字コード | 画面に出る文字列 |
|---|---|---|
| UTF-8 | UTF-8 (一致) | こんにちは |
| UTF-8 | Shift_JIS | 縺薙s縺ォ縺。縺ッ |
| UTF-8 | Latin-1 | 読めない記号が並び、5 文字が 15 文字として数えられる |
| Shift_JIS | UTF-8 | 置換文字 � が大量に並ぶか、まったく別の漢字になる |
4 通りのうち文字列がそのまま読めるのは、保存時と読み出し時の文字コードが一致している 1 行だけです。文字数を数える前に、読み出しに使う文字コードが保存時と同じかどうかを確かめてください。
文字化けが起きる典型的なシナリオは 3 つあります。第一に、ファイルの保存時と読み込み時でエンコーディングが異なるケース。第二に、データベースの接続設定とテーブルの文字セットが不一致のケース。第三に、HTTP レスポンスヘッダの Content-Type で指定した charset と実際の HTML ファイルのエンコーディングが異なるケースです。いずれも「書き手と読み手の約束が合っていない」という同じ構造の問題です。
歴史的に見ると、文字化けは日本のコンピュータ文化と深く結びついています。1980 年代から 1990 年代にかけて、JIS、Shift_JIS、EUC-JP という 3 つの主要な日本語エンコーディングが並立し、メールやウェブページで頻繁に文字化けが発生しました。特に電子メールでは ISO-2022-JP が標準とされていたにもかかわらず、メールクライアントごとに異なるエンコーディングを使うことがあり、受信側で文字化けする問題が日常的でした。
UTF-8 がウェブの事実上の標準になり、文字化けの発生頻度は大幅に減りました。W3Techs の利用状況調査では、2026 年 9 月 5 日時点でウェブサイトの 99.0% が UTF-8 を採用しています。しかし、レガシーシステムとの連携、CSV ファイルのやり取り (Excel は BOM 付き UTF-8 を期待する)、古いデータベースの移行など、文字化けが完全になくなったわけではありません。
文字化けを防ぐ実務上のポイントは、「読む側に文字コードを確実に伝える」か「伝わらない前提で揃えておく」かのどちらかに集約されます。ファイル本体は UTF-8 (BOM なし) で統一し、Excel に渡す CSV だけを BOM 付き UTF-8 として別に書き出します。BOM は Excel には文字コードの目印として役立ちますが、BOM を想定していないプログラムの取り込みでは先頭の項目名が一致せず列の対応が崩れるため、同じ 1 つのファイルで両方を満たそうとしないほうが確実です。データベースの文字セットは utf8mb4 を指定します。MySQL の utf8 は utf8mb3 の別名で 1 文字あたり最大 3 バイトしか使えず、4 バイトを必要とする絵文字や一部の漢字を保存できないため、入力された文字が欠けたり書き込み自体が失敗したりします。HTTP レスポンスには Content-Type: text/html; charset=UTF-8 を明示し、HTML 側の <meta charset> と食い違わせないようにします。ヘッダーと meta の指定が矛盾したときはヘッダー側が使われるため、meta だけ直しても表示は変わりません。
実際に文字化けに出会ったときは、直せるものと直せないものを見分けるのが先です。保存されたバイト列が無傷で、読み出しに使う文字コードの指定だけが食い違っているなら、正しい文字コードで開き直すだけで元の文字列が戻ります。一方、画面に出た置換文字 � を含んだ状態で保存し直すと、その時点で元のバイト列は失われ、あとから復元する手立てはありません。文字化けした状態で検索・置換や再変換をかけて上書き保存した場合も同じです。文字化けに気づいたら、まず上書き保存と再変換を止めて元のデータを退避し、それから読み出し側の指定を変えて試すという順序を守ってください。
文字数カウントの観点では、文字化けしたテキストは見た目の文字数と実際のバイト数が大きく乖離します。たとえば UTF-8 の日本語テキストを Latin-1 として解釈すると、1 文字が 3 文字に膨張して見えるため、文字数カウントの結果が本来の 3 倍近くになることがあります。正確な文字数カウントの前提として、テキストのエンコーディングが正しく認識されていることが不可欠です。