
CSV の RFC 4180 と Excel の独自仕様 — なぜ CSV は壊れるのか
CSVを開くと文字化けしたり、識別番号の先頭ゼロが消えたりすることがあります。文字コード、CSVの構文、表計算ソフトの型推定は別々の問題です。RFC 4180とMicrosoftの案内に沿って、原因を切り分ける方法を整理します。
RFC 4180が記述する共通形式
IETF 情報 RFC 4180 "Common Format and MIME Type for Comma-Separated Values (CSV) Files" は、共通形式とtext/csvを記述するInformational文書であり、Internet Standardではありません。すべてのCSV実装が従う唯一の規格と扱わないでください。要点は以下の ABNF で表現されます:
file = [header CRLF] record *(CRLF record) [CRLF]
header = name *(COMMA name)
name = field
record = field *(COMMA field)
field = (escaped / non-escaped)
escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
non-escaped = *TEXTDATA
COMMA = %x2C
CR = %x0D
DQUOTE = %x22
LF = %x0A
CRLF = CR LF
TEXTDATA = %x20-21 / %x23-2B / %x2D-7E
重要ポイント:
- 記述された形式のレコード区切りはCRLF (\r\n)。最終レコード末尾の改行は省略可
- ダブルクォートで囲んだフィールド内なら カンマ・CR・LF・ダブルクォート を含められる
- フィールド内のダブルクォートは 2つ重ね("")でエスケープ
- MIMEのcharsetは任意で、US-ASCII以外も指定できる
RFC 4180はCSVの共通形式とtext/csvを整理し、MIMEのcharset parameterは任意としています。US-ASCIIは一般的な使用例として挙げられますが、byte列だけで日本語の文字コードまで一意に決める仕様ではありません。
トラブル1: Excel で開くと文字化け (BOM 問題)
Microsoftの案内では、UTF-8のCSVはBOM (0xEF 0xBB 0xBF) 付きなら通常のファイルオープンで開けます。BOMなしのUTF-8 CSVは、Excelの「データ」→「テキストまたはCSVから」等でUTF-8を明示して取り込みます。直接開いたときの推定結果はExcelの版・環境・入口に依存するため、BOMなしを常にShift_JISと断定はできません。
# Python 3: UTF-8 BOM付き・CRLFのCSVを書き出す
import csv
with open("users.csv", "w", encoding="utf-8-sig", newline="") as f:
writer = csv.writer(f, lineterminator="\r\n")
writer.writerows([["name", "id"], ["Renée", "0123"]])この例のBOMは文字コードの手掛かりです。IDを文字列として取り込む指定までは行いません。BOMなしはencodingをutf-8へ変更します。
対処の実務ベストプラクティス:
- Excelで直接開く用途にはUTF-8 BOM付き、他システム向けにはBOM有無を選べるようにする
- BOMなしを渡す場合は、Excelのインポート手順とUTF-8指定を利用者へ案内する
- 読み込み側はBOM・送信元の宣言・利用者の明示設定を優先し、自動判定だけで上書き保存しない
トラブル2: 改行コードで行が崩れる
RFC 4180が記述するレコード区切りはCRLFですが、実際に流通する CSV には3種類の改行が混在します:
- CRLF (\r\n): Windows, RFC 4180 準拠
- LF (\n): Unix, macOS(現行)
- CR (\r): 古い Mac OS (OS X 以前、レガシー)
ファイルの作成OSだけで区切りを決めつけず、作成側と受信側で合意します。引用符内の改行まで一括置換するとセル内容が変わる場合があります。
追い打ちをかける問題: ダブルクォート内の改行も CSV の一部として許可されるため、「行数 = 改行数」とは限らない。雑にファイルを split("\n") で分割するパーサを書くと、改行を含むセルがある CSV を壊します。
# 1行目が "コメント" カラムに改行を含む場合
ID,氏名,コメント
1,田中,"次の行を
参照してください"
2,佐藤,通常のコメント
# 見かけ上4行だが、CSV としては 3 行 (ヘッダ + 2データ行)
トラブル3: 引用符・エスケープのパース失敗
フィールド内にカンマ、ダブルクォート、改行を含む場合のエスケープ規則:
# ソースデータ
氏名: "田中 太郎"
コメント: セミナーに参加, 質問あり
メモ: 複数行
のテキスト
# CSV 表現 (RFC 4180 準拠)
"""田中 太郎""","セミナーに参加, 質問あり","複数行
のテキスト"
注: RFC 4180 でエスケープが必須となるのは 半角カンマ(U+002C)、ダブルクォート、CR/LF のみ。全角句読点「、」はエスケープ対象ではありません。ただし実装上はすべてのフィールドを常に引用符で囲むという方針も使えます。ただし引用符で囲んでも、Excelの型推定や数式解釈を止める保証はありません。
ダブルクォートを含むとき、フィールド全体をダブルクォートで囲み、内部のダブルクォートを2つに倍化します。
よく見る実装の間違い:
- バックスラッシュ
\"でエスケープしてしまう (RFC 4180の引用符エスケープとは異なる) - シングルクォート
'で囲んでしまう (CSV ではダブルクォートのみ有効) - 先頭にダブルクォートがあればエスケープ必須なのに、カンマを含まないフィールドで囲まない (一部のパーサで失敗)
トラブル4: 先頭ゼロ・指数表記・日付の自動変換
CSVにセル型はありません。次は取込方法や地域設定によって起こり得る例で、全環境の固定結果ではありません。
表が収まらない場合は、左右にスクロールできます。
| 元データ | 起こり得る解釈 | 注意点 |
|---|---|---|
| 0123 | 数値123 | 識別番号の先頭ゼロが失われる |
| 3E2 | 数値300 | 文字列としての表記が変わる |
| 3/4 | 日付 | 月日・日月の解釈と年は環境依存 |
| 12345678901234567 | 数値 | Excelの数値精度15桁を超え、元の桁を失い得る |
識別番号や日付に似たコードは、取込時に列をTextとして指定してください。Power Queryで既に型変換された後なら、その変換ステップを確認し、元ファイルからやり直します。失われた桁は表示形式の変更だけでは戻りません。
先頭タブを加える方法は元データを変えます。="0123"は文字列型の宣言ではなくExcelの数式です。未信頼入力を数式へ包む方法は一般的な解決策にしません。引用符の倍化と数式インジェクション対策も別問題です。xlsxを使う場合も、意図したセルを明示的な文字列型で出力します。
地域設定と取込方法を確認する
Windowsの地域設定などによって、Excelの区切り文字がセミコロンになる場合があります。小数点記号とリスト区切りを区別し、受け手がカンマ区切りとして読んでいるか確認してください。
Excel、Google Sheets、LibreOffice Calcを一括して「常にRFC準拠」と判定するのではなく、利用する版・OS・取込経路で、区切り文字、文字コード、引用符、改行、型推定を確認します。まず原本を複製し、既知の少量データで読み込みと再書き出しを照合してください。
代替フォーマットの検討
CSV の仕様曖昧さが問題ならば、以下の代替が有効です:
- TSV (Tab-Separated Values): カンマではなくタブ区切り。フィールド内のカンマを気にせず済む。タブや改行を含む値の扱いは受け手と合意する
- JSON / JSON Lines: 型情報を持つ (string/number/boolean/null/array/object)。大きな整数や日付の扱いは別途合意する
- Excel .xlsx: OOXML 標準。型保持・数式・複数シート対応。SheetJS など JS ライブラリで読み書き可
- Parquet: 列指向バイナリ、大量データ高速処理。BigQuery / Athena 等で採用
- SQLite ファイル: 完全なリレーショナルデータ。SQL で問い合わせ可
形式を変えれば自動的に安全になるわけではありません。受け手の対応、型の保持、データ量、編集方法に合う形式を選びます。
実務チェックリスト
- Excel直接オープンを重視する出力はUTF-8 + BOMを候補にし、他consumer向けに切替可能にする
- 改行はCRLFで統一
- 引用符エスケープはRFC 4180 準拠 ("") 、バックスラッシュ使用しない
- カラムにカンマ・ダブルクォート・改行が含まれる可能性があるなら常に引用符で囲む
- 先頭ゼロ・大きな数値・日付っぽい文字列はExcel で開いた時の挙動をテスト
- 可能なら xlsx / JSON / Parquet での代替を検討
- 読み込み側ではBOM・送信元の宣言・明示設定を優先し、自動判定は候補として内容を照合する
まとめ
- RFC 4180だけでは日本語CSVの文字コードを確定できず、charsetや受渡し手順を別途合意する必要がある
- ExcelでUTF-8 CSVを通常どおり開く互換性を重視するならBOMを付ける。BOMなしは「データの取得」等でUTF-8を明示して取り込める
- RFC 4180の形式で渡すならレコード区切りはCRLF、LF/CR 混在に注意
- 引用符エスケープは
""(ダブルクォート倍化)、バックスラッシュ使用は RFC 違反 - 先頭ゼロ・日付っぽい文字列は Excel 自動変換に注意
- 型保持が必要ならJSON / xlsx / Parquetも検討し、受渡し契約を定める
参考文献・ソース
記事作成に関する注記
本記事は AI(大規模言語モデル)を編集補助として活用して作成しています。 公開前に編集者が内容を確認していますが、事実誤認・仕様の解釈ミス・最新情報との齟齬が含まれる可能性があります。 重要な判断を行う際は、本文中の一次ソースや公式ドキュメントを必ずご自身でご確認ください。 誤りにお気づきの場合は、お問い合わせフォームよりご連絡いただけると助かります。




