Blog 入門

【新卒向け】文字コードとエンコーディング入門 - 文字化けはなぜ起きる?

文字化けはなぜ起きるのかを、文字コードとエンコーディングの仕組みから新卒エンジニア向けにやさしく解説し、Pythonでファイルのエンコーディングを確認・変換する安全な手順までを紹介します。

8 min read [AI生成]

開いたCSVが「譁�蟄怜喧縺�」になる朝

取引先から届いたCSVファイルをExcelで開いたら、顧客名の欄が「譁�蟄怜喧縺�」のような記号の羅列になっていた。中身は壊れていないはずなのに、文字だけが読めない。新卒で現場に入ると、多くの人が最初の数週間でこの場面に出くわします。これが俗に言う「文字化け」です。

文字化けは、ファイルやデータが壊れて起きるわけではありません。ほとんどの場合、データ自体は無傷で、ただ「読み方」を間違えているだけです。この記事では、なぜ読み方を間違えると文字が化けるのかを、文字コードとエンコーディングという2つの仕組みから順に解きほぐしていきます。

文字コード — コンピュータは文字を番号で扱う

まず大前提として、コンピュータは文字そのものを理解しません。扱えるのは数値だけです。そこで「どの文字をどの番号に対応させるか」を決めた巨大な対応表が必要になります。これを 文字コード(または文字集合、character set)と呼びます。

身近なたとえで言えば、座席表のようなものです。「A1番の席は田中さん、A2番は佐藤さん」と決めておけば、席番号を伝えるだけで誰のことか分かります。文字コードも同じで、「65番はA、12354番は『あ』」というように、文字へ番号を割り当てた表です。この番号のことを コードポイント(符号位置)と呼びます。

世界には複数の対応表が存在します。アルファベットと記号だけを定めた古い表が ASCII(アスキー)で、0〜127番の128文字しかありません。これに日本語や中国語、絵文字まで含め、世界中の文字を一つの表にまとめようとしたのが Unicode(ユニコード)です。現在のWebやプログラムはほぼUnicodeを前提に作られています。

つまずきポイント:「文字コード」と「エンコーディング」を同じ意味だと思ってしまう

新卒のうちは、この2語を混同しがちです。文字コードは「文字と番号の対応表」でした。次に説明するエンコーディングは「その番号を、実際にファイルへどう書き込むか」という別の話です。表と、表の保存方法。役割が違うことを先に押さえておくと、この後がぐっと分かりやすくなります。

エンコーディング — 番号をバイトの並びに変換する規則

文字コードで「あ」が12354番だと分かっても、まだ問題が残ります。ファイルに保存できるのは バイト(0〜255の値を取る、データの最小単位のかたまり)の列だけです。12354という番号を、どういうバイトの並びとして書き出すか。そのルールが エンコーディング(符号化方式)です。

同じUnicodeの番号でも、バイトへの変換方法は何種類もあります。代表的なものを挙げます。

  • UTF-8:1文字を1〜4バイトの可変長で表す方式。アルファベットは1バイト、日本語は3バイト程度。現在の世界標準で、迷ったらこれを選びます。
  • Shift_JIS(シフトジス):Windowsの日本語環境やExcelのCSVで古くから使われてきた方式。日本語を2バイトで表します。

ここが文字化けの核心です。保存するとき(エンコード)と読み込むとき(デコード)で、別々のエンコーディングを使うと、同じバイト列をまったく違う文字として解釈してしまいます。冒頭の「譁�蟄怜喧縺�」は、UTF-8で保存された日本語を、Shift_JISだと思い込んで読んだときに典型的に現れる化け方です。バイトは正しく届いているのに、変換表だけがすれ違っている状態です。

つまずきポイント:Excelで開くと化けるからデータが壊れていると思い込む

ExcelはCSVをShift_JIS前提で開くことがあり、UTF-8のファイルだと化けます。しかし同じファイルをテキストエディタでUTF-8指定で開けば、正しく読めます。「アプリによって見え方が変わる」なら、データ破損ではなくエンコーディングのすれ違いを疑うのが先決です。

操作 — エンコーディングを確認してから変換する

仕組みが分かったところで、実際の確認と変換に進みます。ここで使うのは Python 3 です。多くの環境に最初から入っており、OSを問わず同じコードが動きます。ターミナル(コマンドプロンプトやシェル)から実行します。

まず「何のエンコーディングか」を推定する

変換の前に、相手のファイルがどのエンコーディングかを知る必要があります。chardet というライブラリで推定できます。

# Install the detection library first
pip install chardet
import chardet

# Read the file as raw bytes, not as text
with open("customers.csv", "rb") as f:
    raw = f.read()

# Let the library guess the encoding from the byte pattern
result = chardet.detect(raw)
print(result)  # e.g. {'encoding': 'SHIFT_JIS', 'confidence': 0.99, ...}

このコードの読み方です。ポイントは open の第2引数の "rb"で、これは「バイトとして」読む指定です。エンコーディングがまだ分からない段階で文字として読もうとすると、その時点で化けたり失敗したりするため、あえて生のバイトのまま受け取っています。detect はバイトの並び方のクセから推定し、encoding(推定した方式)と confidence(確からしさ、0〜1)を返します。あくまで推定なので、confidence が低いときは結果を鵜呑みにしない姿勢が大切です。

読み込みと書き出しで、それぞれ正しい方式を指定する

エンコーディングが分かれば、変換は「正しい方式で読み、別の方式で書く」だけです。ここではShift_JISのCSVをUTF-8に変換します。

# Read with the encoding it was actually saved in
with open("customers.csv", "r", encoding="shift_jis") as f:
    text = f.read()

# Write a new file with the target encoding
with open("customers_utf8.csv", "w", encoding="utf-8") as f:
    f.write(text)

読み方のコツは、encoding= を読み込み側と書き出し側の両方で明示している点です。Pythonは encoding を省略すると実行環境の既定値を使うため、環境が変わると挙動も変わります。省略は文字化けの温床なので、常に書くクセをつけてください。変換は元ファイルを上書きせず、customers_utf8.csv という新しい名前で保存しています。

つまずきポイント:読めてしまうが、実は一部だけ化けている

Shift_JISとして読んでもエラーが出ず、しかし一部の文字だけ化けることがあります。読み込み時に errors="strict" を付けると(これは既定の動作です)、解釈できないバイトに出会った時点で例外を投げて止まります。黙って別の文字に置き換えるより、止まって気づけるほうが安全です。異常を握りつぶさないことが、データを扱う仕事の基本姿勢になります。

安全な習慣 — 元ファイルを壊さずに変換する

現場でエンコーディング変換を行うとき、プロが必ず守る習慣があります。元のファイルを直接上書きしないことです。上の例で別名保存したのは、このためです。

変換は一方向ではうまくいかないことがあります。推定を誤れば、変換後のファイルはさらに激しく化けます。元ファイルが手元に残っていれば、方式を変えて何度でもやり直せます。上書きしてしまうと、化けた状態からは元に戻せません。「取り返しのつかない操作の前に、元を残す」。これはエンコーディングに限らず、データを扱うあらゆる場面で効いてくる考え方です。

まとめ

今日の内容を、頭の中のイメージとして整理しておきます。

  • 文字コードは「文字と番号の対応表」。座席表のように、文字へ番号を割り当てたもの(ASCII、Unicodeなど)。
  • エンコーディングは「番号を実際のバイト列へ変換する規則」。同じUnicodeでもUTF-8やShift_JISなど複数ある。
  • 文字化けは、保存時と読み込み時でエンコーディングがすれ違って起きる。データ破損ではなく「読み方」の問題。
  • 変換は、正しい方式で読み、別の方式で書くだけ。ただし encoding は必ず明示し、元ファイルは上書きしない。

次の一歩として、今日のうちに手元のテキストエディタ(VS Codeなど)で、適当なファイルを開いて画面の端にある文字コード表示を探してみてください。多くのエディタは現在のエンコーディングを常に表示し、クリックで切り替えられます。「今このファイルは何で読まれているのか」を意識する習慣が、文字化けに動じない第一歩になります。

※ この記事はAIが自動生成したものです。本記事の内容は執筆時点の情報であり、正確性を保証するものではありません。ご利用の際は免責事項をご確認ください。

Share

Related / 関連記事

関連記事

Comments / コメント

コメント