合同会社小村ソフト
第 1 章

導入 — 文字化けはなぜ起きるか

ファイルの実体はバイト列だけ。「書いた符号化」と「読んだ符号化」がズレると同じバイト列が別の文字に見える — 文字化けの正体をここで押さえる。

「縺薙s縺ォ縺。縺ッ」— この画面、何が起きているのか

取引先から届いた CSV を Excel で開いたら日本語が全部「縺薙s縺ォ縺。縺ッ」のような漢字の羅列になっていた。Web ページの一部だけ「ã“ã‚“」のような記号が並ぶ。DB に登録したはずの名前が「????」になっている。— 対処として「符号化を変えて開き直したら直った」経験はあっても、なぜそれで直るのかを説明できる人は意外と少ないものです。

出発点はたった 1 つの事実です。コンピュータが保存したり送ったりできるのは、0x00〜0xFF のバイトの並びだけ。「あ」や「A」という文字そのものが保存されているわけではありません。文字をバイト列に変換する規則を符号化(エンコーディング)と呼び、UTF-8 も Shift_JIS もこの規則の一種です。

そして重要なのが次の点です。ファイルには「このバイト列は UTF-8 です」という札は付いていません。読む側は、設定や宣言や推測を頼りに「たぶんこの符号化だろう」と決めて対応表を引きます。書いた側の規則と読む側の規則が一致していれば元の文字に戻り、ズレていれば — 別の文字に見えます。これが文字化けです。

バイト列 E3 81 AB が UTF-8 では「に」、Shift_JIS では「縺ォ」、Latin-1 では「ã«」と読まれることを示す図

同じ 3 バイトが、引く対応表によって「に」「縺ォ」「ã«」に化けます。バイト列は 1 ビットも変わっていない、という点が最大のポイントです。

化けても、データは壊れていない

上の図をもう一度見てください。E3 81 AB という 3 バイトは、どの読み方をしてもまったく同じ 3 バイトのままです。壊れたのはデータではなく「読み方の選択」だけ。だから、正しい符号化を指定して読み直せば、元の「に」がそのまま戻ってきます。

ただし 1 つだけ注意があります。化けた見た目のまま上書き保存してしまうと、「縺ォ」という化けた文字列が新しいバイト列としてディスクに書き込まれ、元のバイト列は失われます。文字化けに出会ったら「書き込まずに、まず読み方を疑う」— これが実務での第一動作です。

この講座の合言葉: 文字化けを見たら問いかけてください — どの符号化で書かれたバイト列を、どの符号化として読んでしまったのか?

小問 1-1 — ファイルの実体はバイト列だけ

文字化けの正体を、バイト列と読み方の関係として言えるかを確認します。

Q1. テキストファイルとしてディスクに保存されている「実体」は何ですか。

Q2. 同じバイト列 E3 81 AB を UTF-8 として読むと「に」、Shift_JIS として読むと「縺ォ」に見えます。この現象の説明として正しいものはどれですか。

Q3. 文字化けしたファイルについて、多くの場合に正しい説明はどれですか。

「番号を振る」と「バイトにする」— 2 段階に分けて考える

ここで、この講座全体を貫く見方を導入します。文字がバイト列になるまでには、実は 2 つの独立した段階があります。

第 1 段階 — 文字集合(どの文字に番号を振るか)
世の中の文字を集めて、1 つずつ番号を割り当てた表。Unicode では「あ」に U+3042 という番号が振られています。この番号をコードポイントと呼びます
第 2 段階 — 符号化(番号をどうバイトにするか)
コードポイントをバイト列へ変換する規則。同じ U+3042 でも、UTF-8 なら E3 81 82、UTF-16 なら 30 42 と結果は変わります

「Unicode と UTF-8 って何が違うの?」という定番の疑問は、この 2 段階で即答できます。Unicode は第 1 段階(番号の振り方)、UTF-8 は第 2 段階(番号のバイトへの変え方)。土地の番地の決め方と、番地を封筒にどう書くかの違い、と言ってもよいでしょう。第 2 章で第 1 段階を、第 3 章以降で第 2 段階を、それぞれじっくり扱います。

小問 1-2 — 文字集合と符号化を区別する

この講座を貫く 2 段階 — 番号を振る(文字集合)とバイトにする(符号化)— の区別を確認します。

Q4. 「文字集合」と「符号化」の役割分担として正しいものはどれですか。

Q5. 「このファイルは Unicode で保存されています」という言い方が不正確な理由はどれですか。

この章で持ち帰ること

  • ファイルの実体はバイト列だけ。「何の符号化か」の札は付いていない
  • 文字化けの正体は「書いた符号化」と「読んだ符号化」のズレ。バイト列そのものは壊れていないことが多く、読み方を直せば戻る(ただし化けたまま保存しない)
  • 文字は番号(コードポイント)→ バイト列(符号化)の 2 段階で扱われる。Unicode は第 1 段階、UTF-8 は第 2 段階

次章では第 1 段階「番号を振る」の歴史を、ASCII の 128 文字から世界中の文字を収める Unicode まで一気にたどります。