3秒でわかる
文字に番号を割り当て、その番号をバイト列として表すための規則。書き出した側と読み込む側で規則が食い違うと、文字化けが起こります。
もう少し詳しく
どういうものか
文字コードは、文字と数値の対応、およびその数値をどうバイトに並べるかを決めた規則です。厳密には 2 段階に分かれます。文字に番号を振るのが文字集合、番号をバイト列に変換するのが符号化方式です。
Unicode は文字集合で、世界中の文字に番号を振ります。UTF-8 や UTF-16 はその番号をバイトにする方式です。日本語では他に Shift_JIS や EUC-JP があり、これらは文字集合と符号化がほぼ一体になっています。
なぜ必要か
コンピュータはバイト列しか保存できません。同じバイト列でも、どの規則で読むかによって別の文字になります。書き出したときの規則と読み込むときの規則が食い違うと、文字化けとして現れます。
UTF-8 が広く使われているのは、英数字が 1 バイトのままで従来の形式と互換があり、日本語を含む世界中の文字も同じ規則で表せるためです。日本語は 1 文字 3 バイトになるのが一般的です。
具体例
s = "あ"
print(s.encode("utf-8")) # b'\xe3\x81\x82' 3バイト
print(s.encode("shift_jis")) # b'\x82\xa0' 2バイト
# 別の規則で読むと化ける
print(s.encode("utf-8").decode("shift_jis")) # 縺・
# ファイルは規則を明示して開く
with open("data.csv", encoding="utf-8") as f:
text = f.read()Linux では、規則を調べたり変換したりできます。
file -i data.csv # 推定した文字コードを表示
iconv -f shift_jis -t utf-8 old.csv > new.csvつまずきやすいところ
Windows で作った CSV が典型的な事故の元です。Excel が Shift_JIS で保存するため、UTF-8 前提のプログラムで読むと UnicodeDecodeError になります。読み込み側で encoding="cp932" を指定するか、保存側を UTF-8 に変える必要があります。
BOM も引っかかりやすい点です。UTF-8 の先頭に付く 3 バイトの印で、そのまま読むと最初の列名の頭に見えない文字が混ざり、キーが一致しなくなります。Python では encoding="utf-8-sig" で取り除けます。
文字数の数え方も規則で変わります。絵文字や一部の漢字は Unicode 上で 2 単位分を占めるため、言語によって length の結果が食い違います。
覚え方
「書いたときと同じ規則で読む」。文字化けの原因はほぼこれ 1 つです。