DevToolBox

文字化けの原因と直し方:UTF-8・Shift_JIS・BOMの違いを化け方から見分ける

公開日:

CSVをExcelで開いたら日本語が読めない記号の列になった、メールやログの日本語が「縺薙s縺ォ縺。縺ッ」のようになった――こうした文字化けは、ほとんどの場合「書いた側」と「読んだ側」で文字コードの解釈が食い違っていることが原因です。この記事では、文字化けが起きる仕組みと、化け方から原因を推測するコツ、よくある場面ごとの対処法をまとめます。

文字化けは「バイト列の読み違い」で起きる

コンピューターは文字をそのまま保存しているわけではなく、決められたルール(文字コード、エンコーディング)で文字を数値の並び(バイト列)に変換して保存しています。日本語でよく使われる文字コードは次のとおりです。

文字コード 特徴 「日本語」のバイト列
UTF-8 世界中の文字を扱える現在の標準。日本語は主に1文字3バイト E6 97 A5 E6 9C AC E8 AA 9E
Shift_JIS(CP932) 古いWindowsや日本の業務システムで多い。日本語は1文字2バイト 93 FA 96 7B 8C EA
EUC-JP 古いUnix系システムで使われていた (省略)

同じ「日本語」という文字でも、文字コードが違えばバイト列はまったく別物です。UTF-8で保存したファイルをShift_JISとして読むと、バイト列の区切り方も対応する文字も変わってしまい、意味のない文字の並びが表示されます。これが文字化けです。

データそのものが壊れているとは限らない、という点が重要です。多くの場合、正しい文字コードで読み直せば元の文字が表示されます。慌てて上書き保存すると、化けた状態で保存されて本当に復元できなくなることがあるため、まずは保存せずに原因を確かめましょう。

化け方から原因を推測する

文字化けには、組み合わせごとに特徴的なパターンがあります。次の例は、実際にそれぞれの組み合わせで読み違えた結果です。

元の文字 書いた側 → 読んだ側 表示される文字
こんにちは UTF-8 → Shift_JIS 縺薙s縺ォ縺。縺ッ
テスト UTF-8 → Shift_JIS 繝�繧ケ繝�
テスト UTF-8 → Windows-1252(欧文) テスト
テスト Shift_JIS → UTF-8 �e�X�g

見分けるポイントは次の3つです。

  • 「縺」「繧」「繝」などの見慣れない漢字が多い:UTF-8のデータをShift_JISとして読んでいる。UTF-8のひらがな・カタカナはE3 81〜E3 83で始まるバイト列になり、Shift_JISではこれが「縺」「繧」「繝」などの漢字として解釈されるため、この形になりやすい
  • 「ã」「Ã」などアクセント付きの欧文字が並ぶ:UTF-8のデータを欧文用の文字コード(ISO-8859-1やWindows-1252)として読んでいる
  • 「�」(置換文字)が並ぶ:UTF-8として読もうとしたが、UTF-8として正しくないバイト列だった。Shift_JISなど別の文字コードのデータである可能性が高い

よくある場面と対処法

ExcelでCSVを開くと文字化けする

日本語版のExcelは、BOM(後述)のないCSVをShift_JISとして読み込むことが多いため、UTF-8で出力したCSVをダブルクリックで開くと文字化けしやすくなります。Excelのバージョンや開き方によって挙動が異なりますが、対処法は主に次の3つです。

  • 出力する側で、UTF-8にBOMを付けて保存する(BOM付きUTF-8)。多くのExcelで正しく開ける
  • Excelの「データ」タブから「テキストまたはCSVから」で取り込み、文字コードに「65001: Unicode (UTF-8)」を指定する
  • 受け取る側がExcelに限られる場合は、Shift_JISで出力する(ただし、Shift_JISで表せない文字は失われる)

BOM(バイトオーダーマーク)とは

BOMは、ファイルの先頭に付けるEF BB BFの3バイトで、「このファイルはUTF-8です」という目印になります。Excelのように目印があると正しく読めるソフトがある一方で、BOMがあると困る場面もあります。

  • シェルスクリプトの1行目(#!/bin/bash)の前にBOMがあると、正しく実行されない
  • PHPファイルの先頭にBOMがあると、余計な出力として扱われ、ヘッダー送信のエラーの原因になる
  • JSONの仕様(RFC 8259)では、ネットワークで送るJSONの先頭にBOMを付けてはならないと定められており、BOM付きのJSONを受け付けないパーサーもある

プログラムや設定ファイルはBOMなし、Excelで開くCSVはBOM付きと使い分けるのが無難です。

Webページやメールで文字化けする

Webページの場合は、サーバーが返すContent-Type: text/html; charset=utf-8ヘッダーと、HTMLの<meta charset="utf-8">が、実際のファイルの文字コードと一致しているかを確認します。宣言がない、または実際と違う宣言をしていると、ブラウザが文字コードを推測して誤ることがあります。

URLやBase64の中の日本語が化ける

URLエンコードやBase64は、文字そのものではなくバイト列を変換する仕組みです。そのため、同じ文字でも元の文字コードによって結果が変わります。

  • 「あ」をUTF-8でURLエンコードすると%E3%81%82、Shift_JISでは%82%A0になる
  • 古いシステムからShift_JISでURLエンコードされた値を受け取り、UTF-8としてデコードすると文字化けする

JavaScriptのbtoa()は、日本語などを直接渡すとInvalidCharacterErrorというエラーになります。先にTextEncoderでUTF-8のバイト列に変換してからBase64にする必要があります。本サイトのURLエンコード・デコードツールとBase64エンコード・デコードツールは、どちらもUTF-8として変換します。

「~」や「①」が化ける:Shift_JISの方言の問題

Shift_JISには、Windowsが独自に拡張したCP932(Windows-31J、MS932とも呼ばれる)という方言があります。「①」「㈱」「Ⅲ」などの文字はCP932で追加されたもので、厳密なShift_JISとして扱うシステムでは化けたり、「?」に置き換わったりします。

また、同じバイト列81 60が、Shift_JISでは「〜」(U+301C、波ダッシュ)に、CP932では「~」(U+FF5E、全角チルダ)に対応づけられています。システム間で変換表が違うと、「〜」が化けたり、見た目は同じでも別の文字として扱われて検索や比較に失敗したりします。いわゆる「波ダッシュ問題」です。

文字化けの原因を調べるときは、Unicodeエスケープツールで文字を\u301Cのようなコードポイントに変換すると、見た目が似た文字の違いをはっきり確認できます。

文字化けを防ぐための基本方針

  • 新しく作るファイル・システムはUTF-8に統一する。HTML・JSON・ソースコード・データベースの文字コード設定をそろえる
  • 外部とのやり取りでは文字コードを明示する。CSVの仕様書、APIのContent-Type、メールのヘッダーなどに書いておく
  • 文字化けしたファイルを上書き保存しない。まず正しい文字コードで開き直す(VS Codeでは、ステータスバーの文字コード表示から「エンコード付きで再度開く」を選べる)

まとめ

  • 文字化けは、書いた側と読んだ側の文字コードの食い違いで起きる
  • 「縺」「繧」ならUTF-8をShift_JISで、「ã」ならUTF-8を欧文で、「�」ならUTF-8以外のデータをUTF-8で読んでいる可能性が高い
  • ExcelでCSVを開く場合はBOM付きUTF-8、プログラムや設定ファイルはBOMなしが基本
  • 「~」「①」などの記号は、Shift_JISとCP932の違いで化けることがある

参考

この記事で紹介したツール

テキストをURLエンコード・デコードします。

テキストをBase64にエンコード・デコードします。

おすすめ

非ASCII文字を\uXXXX形式にエスケープ・アンエスケープします。