別の環境で開いたファイルが、画面いっぱいに「縺ゅ◇縺・」のような呪文を並べていた。
そんな文字化けに、私は何度ぎょっとさせられたか分かりません。
中身は壊れていないのに、文字だけが知らない言語に化けてしまう。
その犯人は、ふだん意識しない文字コードのすれ違いです。
この記事では、文字化けがなぜ起きるのかを、バイトと文字の関係からほどいていきます。
文字コードは「バイトと文字」の対応表
コンピュータが扱えるのは、突き詰めれば 0 と 1 が並んだバイトの列だけです。
その数値の並びを「この番号はこの文字」と決めた約束ごとが、文字コードと呼ばれるもの。
たとえば同じ「あ」でも、どの約束ごとを使うかで割り当てられるバイトが変わります。
# 同じ「あ」でも文字コードで割り当てが変わる
>>> "あ".encode("utf-8")
b'\\xe3\\x81\\x82' # UTF-8 では 3 バイト
>>> "あ".encode("shift_jis")
b'\\x82\\xa0' # Shift_JIS では 2 バイト
つまり保存するときと読むときで違う約束ごとを使えば、当然ながら別の文字に化ける。
代表的な文字コードの違い
日本語を扱う現場では、長らく複数の文字コードが併存してきました。
いまの標準は UTF-8
現在のWeb・アプリ開発で事実上の標準になっているのが UTF-8 です。
1文字を1〜4バイトの可変長で表し、世界中の文字を一つの体系で扱えるのが強み。
しかも先頭の128文字はASCIIとバイト単位で互換なので、英数字だけの設定ファイルはそのまま読めます。
まだ出会う Shift_JIS
一方、古いWindows環境や既存システムでは Shift_JIS がいまも残っています。
同じ「あ」を2バイトで表すなど、UTF-8 とはバイトの並びがまったく違う。
新規に選ぶ理由はほぼありませんが、受け取ったファイルが Shift_JIS だった、という遭遇は今も起こります。
なぜ文字化けは起きるのか
文字化けの正体は、ほとんどが「保存した約束ごと」と「読んだ約束ごと」のズレです。
UTF-8 で保存したファイルを Shift_JIS だと思い込んで開けば、バイトの解釈がずれて別の文字に化ける。
# 読み込み時は encoding を必ず明示する
with open("memo.txt", encoding="utf-8") as f:
text = f.read()
# encoding を省くと OS のデフォルトに依存し、化けの温床になる
やっかいなのは、ファイル自身が「私は何コードです」と名乗ってくれないこと。
だから読む側が正しいコードを指定するか、正しく推測してやる必要があります。
BOM という小さな目印
この「名乗らない」問題への、ささやかな目印が BOM(Byte Order Mark)です。
UTF-8 の BOM は、ファイル先頭に置かれる EF BB BF という3バイト。
「このファイルは UTF-8 です」という署名として働きます(W3Cの解説)。
ただし便利な反面、シェルスクリプトやJSONでは余計な一文字として悪さをすることもある。
つけるか外すかは、扱うツールが BOM をどう解釈するかで決めるのが安全です。
文字化けを防ぐ習慣
仕組みが分かれば、対策は驚くほど単純になります。
- 迷ったらUTF-8 に統一する:新規ファイルは理由がない限り UTF-8(BOMなし)で保存する
- エンコーディングを明示する:読み書きを環境のデフォルト任せにしない
- 文字コード表示を確認する:エディタで開いた瞬間に何コードかを見る癖をつける
改行コードと同じで、人の注意力ではなく設定やコードに約束を肩代わりさせるのが結局いちばん楽。
改行コードも同じ「見えない制御の世界」の話なので、あわせて読むと腑に落ちると思います。
最後に
文字化けは、一見すると不気味な現象に見えます。
けれど正体は「保存と読み取りで約束ごとがずれた」だけの、とても素直なすれ違い。
UTF-8 への統一と、エンコーディングの明示。この2つを習慣にするだけで、あの呪文に悩まされる回数はぐっと減ります。
以上です。










コメントを残す