CreaTools LogoCreaTools
Tips

UTF-8なのに文字化け?BOMの有無を確認しろ

2025-10-30

結論:ExcelはBOM付きUTF-8が必要

開く側必要なエンコーディング
Excel(Windows)UTF-8(BOM付き)またはShift_JIS
ブラウザUTF-8(BOMなし)
GoogleスプレッドシートUTF-8

同じUTF-8でも、BOMの有無で動作が変わる。


BOMとは

Byte Order Mark。ファイル先頭にある「これはUTF-8ですよ」という3バイトの目印。

種類先頭バイト
UTF-8 BOMEF BB BF

BOMの有無で変わること

用途BOMなしBOM付き
Web✓ 推奨△ 動くが非推奨
Excel(Windows)✗ 文字化け✓ 正常
PHP✓ 正常✗ 空白が出る

文字化けが起きる典型パターン

1. CSVをExcelで開いたら文字化け

原因:BOMがない。

ExcelはBOMがないと「これはUTF-8だ」と認識できず、別のエンコーディングで開こうとする。

# BOMを付けて保存
echo -ne '\xEF\xBB\xBF' | cat - input.csv > output.csv

2. PHPの出力の前に空白が入る

原因:BOM付きで保存している。

PHPは<?phpの前にある文字をそのまま出力する。BOMの3バイトが空白として出る。

エディタで「BOMなしUTF-8」で保存し直す。


私がやらかした失敗

クライアント「CSVが文字化けしてます」 私「UTF-8で出力してますけど…」

BOMの存在を知らなかった。

調べたら、WindowsのExcelはBOMがないとUTF-8を認識しない。BOMを付けたら解決。

「UTF-8で出力したから大丈夫」は思い込み。相手の環境を確認する。


改行コードの問題

OS改行コード
Windows\r\n(CRLF)
Mac/Linux\n(LF)

改行が全部消えた

Windowsで作ったファイルをMacで開いたら、改行が変な位置に。

GitでLFに統一するのが一般的。

# .gitattributes
* text=auto eol=lf

エンコーディングの確認方法

# ファイルのエンコーディングを確認
file -i target.csv
# → target.csv: text/plain; charset=utf-8

VS Codeなら右下のステータスバーに表示。クリックで変更可能。


変換コマンド

# Shift_JIS → UTF-8
iconv -f SJIS -t UTF-8 input.csv > output.csv

# UTF-8 → Shift_JIS(Excel向けに安全策)
iconv -f UTF-8 -t SJIS input.csv > output.csv

Excel向けCSV出力(PHP例)

header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="data.csv"');

// BOMを出力
echo "\xEF\xBB\xBF";

$fp = fopen('php://output', 'w');
foreach ($data as $row) {
    fputcsv($fp, $row);
}
fclose($fp);

まとめ

  • ExcelはBOM付きUTF-8が必要
  • WebはBOMなしUTF-8
  • PHPでBOM付きだと空白が出る
  • file -iでエンコーディングを確認
  • GitでLFに統一しておく