チェック・トラブル対処Read this article in English

文字化けの読み方 — 「縺ゅ↑縺溘」から元のテキストに戻す方法

ファイルを開いたら「縺ゅ↑縺溘」のような意味不明な文字列が出てきた — この状態を見て「データが壊れた」と思いがちですが、実際にはディスク上のバイト列はほぼ確実に無事です。何が起きたかというと、どこかのプログラムがそのバイト列を間違ったエンコーディングで読み込み、正しいバイトを間違った文字に変換してしまっただけです。この違いは重要で、直すべきはテキストの中身ではなく「どの読み込みが間違えたか」を特定して元に戻すことです。

文字化け=デコードのズレであって、データ消失ではない

テキストファイルは単なるバイト列です。それを画面上の文字にするには、そのバイト列がどのエンコーディングかをプログラムが知る(あるいは推測する)必要があります。この推測が外れると、各バイトは何らかの文字にはなりますが、書いた側が意図した文字にはなりません。見た目は壊れていますが、元のバイト列自体は変わらずそこにあるので、多くの場合は復元可能です。

これは、文字の途中で切れて欠損したファイルや、別内容で上書きされたファイルとは違います。文字化けは規則的です。ファイル全体に同じ間違ったマッピングが一貫して適用されるため、パターンさえ分かれば読み解けます。

化け方のパターンから原因のエンコーディングを特定する

文字化けの見た目には、どのデコーダーが使われたかを示す特徴的なサインがあります。

  • UTF-8のバイト列をShift_JISやCP932として読んだ場合(日本語でよくあるパターン): 「あなた」が「縺ゅ↑縺溘」になるように、脈絡のない漢字・ひらがなが密集して並びます。
  • UTF-8のバイト列をISO-8859-1やWindows-1252のような1バイト系エンコーディングとして読んだ場合: 1つのUTF-8多バイト文字が、ä(ä)やö(ö)のようにアクセント付きラテン文字2〜3文字に分解されます。いわゆる「Ã」パターンです。
  • 1バイト系やShift_JISのファイルをUTF-8として読んだ場合: 多くのバイト列を解釈できず、デコーダーがU+FFFD REPLACEMENT CHARACTERに置き換えるため、⯑や四角い箱の連続になります。
  • 見た目は崩れておらず、特定の箇所だけ違う文字になっている場合: これは一般的な文字化けではなく、CP932とJISで波ダッシュのマッピングが違うといった、ピンポイントな置き換えの可能性が高く、対処法も別になります。

ファイルを復元する方法

正しい直し方は、元のバイト列を正しいエンコーディングで読み直すことであり、化けた文字列を検索置換することではありません。検索置換は化けた文字列を1パターンずつ潰す対症療法で、想定していない組み合わせを取りこぼしたり、たまたま似ている正常な文字列まで壊したりします。読み直しであれば原因そのものに対処するため、一度ですべての箇所が直ります。

実務では、まずファイルが実際どのエンコーディングなのかを特定します(出所から分かることが多く、日本語ロケールの表計算ソフトからの書き出しならShift_JISやCP932の可能性が高く、Webフォームからの入力ならUTF-8の可能性が高いです)。特定できたら、ツールの自動判定や既定値に任せず、そのエンコーディングを明示して生のバイト列を読み直します。元のバイト列が手元になく、すでに化けた文字列しか残っていない場合は、化けた文字列をその原因となった間違ったエンコーディングで一度バイト列にエンコードし直し、それを正しいエンコーディングでデコードすることで復元できることがあります。

// 例: UTF-8のバイト列をCP932/Shift_JISとして誤って読んでしまった場合
// 復元するには、逆順で同じ2ステップをたどる。
// 表示に使われた「間違ったエンコーディング」でエンコードし直し、
// 本来使うべき「正しいエンコーディング」でデコードする。
const garbled = "縺ゅ↑縺溘";
const bytes = encodeWith(garbled, "Shift_JIS"); // 元のUTF-8バイト列を復元
const fixed = decodeWith(bytes, "UTF-8"); // "あなた"

復元できないケース

この復元方法は、元のバイト列がパイプラインのどこかにまだ残っている場合にしか使えません。一度文字化けした状態のファイルを、その化けた文字のままさらに保存し直してしまうと(特に保存時に化けた文字がUTF-8として再エンコードされると)、元のバイト列は失われます。ディスク上に残るのは「間違った文字」を新しく正しくエンコードしただけのファイルであり、そこから元のテキストを逆算する確実な方法はありません。

U+FFFD REPLACEMENT CHARACTERが出てきた場合も同様です。これはデコーダーがあるバイト列をまったく解釈できず、破棄して代わりにプレースホルダーを入れたことを意味します。この置き換えが起きて保存されてしまった時点で、元のバイト列は完全に失われています。U+FFFDは何に置き換わったかの情報を一切持っていません。

再発を防ぐには

文字化けは、ファイルがツール・システム・人の間を渡る「境界」で起きます。効果があるのは、書き出し・読み込み・パイプライン上の各ツールといった、すべての境界でエンコーディングを自動判定に任せず明示的に固定することです。自動判定は優秀ですが完璧ではなく、一度の誤判定がそのまま保存されて次工程に渡ってしまうことこそが、文字化けを復元不能にする典型的な経路です。

関連記事