なぜExcelでCSVが文字化けするのか。BOMとShift_JISの話

2026-09-23

CSVをExcelで開いたら日本語が記号の羅列になった、という経験は多いと思う。原因は壊れたファイルではなく、Excelが何のつもりでそのファイルを読んだかにある。

文字コードは「どのバイト列をどの文字と読むか」の取り決め

同じ内容のCSVを、4つの文字コードで保存してバイト数を測った。

名前,年齢,住所
山田太郎,30,東京都
文字コードバイト数先頭6バイト
UTF-847E5 90 8D E5 89 8D
UTF-8 + BOM50EF BB BF E5 90 8D
Shift_JIS (CP932)3496 BC 91 4F 2C 94
EUC-JP34CC BE C1 B0 2C C7

先頭の「名」という1文字が、UTF-8では E5 90 8D、Shift_JISでは 96 BC になる。同じ文字でも、バイト列は文字コードごとに違う。

だから、UTF-8で書かれたバイト列をShift_JISのつもりで読むと、E5 90 8D を「縺榊」のような別の文字として解釈してしまう。これが文字化けだ。

Excelは、目印が無いとShift_JISとして読む

Windowsの日本語環境では、ExcelはCSVを開くときCP932(Shift_JISの拡張)として読もうとする。UTF-8で保存したCSVをそのまま開くと化けるのはこのためだ。

これを避けるのがBOMで、ファイルの先頭に付ける3バイトの目印だ。

EF BB BF

上の表で、UTF-8が47バイト、UTF-8+BOMが50バイトになっているのがそれだ。この3バイトが「これはUTF-8です」と伝える。 Excelはそれを見てUTF-8として読む。

新しいバージョンのExcelでは改善されている場合もあるが、BOMを付けておけば環境を問わず確実になる。

このサイトのツールに「Excelで開けるようにする」というボタンを置いているが、中身はUTF-8 + BOM + CRLFにしているだけだ。

化けた文字は、たいてい元に戻せる

文字化けを見ると壊れたように見えるが、バイト列そのものは無傷のことが多い。読み方を間違えているだけなので、正しい文字コードで読み直せば元に戻る。

戻らないのは、化けた状態で保存し直したときだ。「縺榊」という文字として保存されてしまうと、そこから元の文字は復元できない。

だから、化けたファイルを見たら保存せずに閉じるのが正しい。

Shift_JISのほうが小さい

表を見て意外に思うかもしれないが、日本語のCSVはShift_JISのほうが小さい。47バイト対34バイトで、3割近く違う。1文字あたりで見るとこうなる。

文字UTF-8Shift_JIS
あ3バイト2バイト
漢3バイト2バイト
A1バイト1バイト
ア(半角カナ)3バイト1バイト

UTF-8は世界中の文字を扱える代わりに、日本語1文字に3バイト使う。Shift_JISは日本語のために作られているので2バイトで済む。

とはいえ、いまどき数十%のサイズ差でShift_JISを選ぶ理由は薄い。選ぶとしたら、次の節の理由のほうが重い。

Shift_JISにすると、消える文字がある

Shift_JISに変換できない文字がある。変換すると、その文字は失われる。

文字Shift_JIS(CP932)
①丸数字87 40
㈱括弧付き87 8A
Ⅷローマ数字87 5B
♥ハート変換不可
𠮟「叱」の異体字変換不可
🍣絵文字変換不可

丸数字や㈱は通る。これらは「機種依存文字」と呼ばれて嫌われてきたが、CP932には含まれている。

一方、絵文字とUnicodeの拡張領域の漢字は通らない。人名に使われる異体字がここに入ることがあるので、名簿をShift_JISにするときは注意がいる。

「ソ」と「表」が壊れる話

もうひとつ、Shift_JIS特有の厄介な性質がある。

Shift_JISの2バイト文字のうち、2バイト目が 0x5C になるものがある。0x5C はバックスラッシュ(日本語環境では円記号)のコードだ。

CP932で調べると、該当する文字は37文字あった。

ソ 予 偆 兔 十 喀 噂 圭 媾 彌 拿 暴 曾 杤 構 欺 歃 浬 濬 申 畚
砡 禄 秉 箪 綵 能 臀 藹 蚕 表 觸 貼 軆 鐔 饅 鷭

「ソ」「表」「十」「能」「貼」「構」「暴」あたりは、普通のCSVに出てくる。

何が起きるかというと、文字コードを意識せずに1バイトずつ読むプログラムが、2バイト目の 0x5C をエスケープ記号だと勘違いする。結果、その次の文字が消えたり、引用符の対応が崩れて列がずれたりする。

「ソ」で始まるデータで不具合が出る、という話は昔から知られていて、「ダメ文字」と呼ばれている。UTF-8では起きない。

どれを選べばいいか

やりたいこと選ぶもの
Excelで開きたいだけUTF-8 + BOM。文字が失われない
古いシステムに渡すShift_JIS。ただし消える文字が無いか確認する
プログラムで処理するUTF-8(BOMなし)
相手の環境が分からないUTF-8 + BOM

迷ったらUTF-8 + BOMでいい。Excelで開けて、文字も失われない。Shift_JISを選ぶのは、相手がそれしか受け付けないと分かっているときだけだ。

計測の条件

Python 3 の標準エンコーダで測った。Shift_JIS は Windows で使われる拡張版のCP932 を指定している。ダメ文字の一覧は、U+3000 から U+9FFF の範囲でCP932 に変換し、2バイト目が 0x5C になるものを数えた。

この記事に対応するツール