CSVの歴史(ざっくり)
“Comma-Separated Values” は「表データをテキストでやりとりする」実務の都合から広まった形式です。
- 表計算・データ交換の現場で、アプリやOSをまたいで扱える“最低限の共通形式”として定着。
- 仕様が1枚岩ではないのが特徴(同じCSVでも、区切りがカンマ/タブ/セミコロン、改行やクォートの扱いが微妙に違う)。
- 後に相互運用のための整理として、慣習やRFC(例:RFC 4180)が参照されるようになったが、現実は「相手のCSVに合わせる」が多い。
現場あるある:
「Excelで開くと文字化け」「カンマ入りの住所が列ズレ」「改行入りセルで地獄」
→ だからこそ ルール(クォート/文字コード/改行)を押さえるのが重要。
CSVの基本ルール
“だいたいこう” の共通点と、事故りやすいポイント。
1) 区切り文字(delimiter)
- 一般的には カンマ(,)。地域や環境によって セミコロン(;) や タブ(TSV) も多い。
2) 1行=1レコード、改行=行区切り
- 改行コードは LF または CRLF。混在するとツール次第で崩れます。
3) ダブルクォート(")の扱い
- 値の中に カンマ / 改行 / ダブルクォート が含まれる場合、フィールド全体を "で囲うのが定番。
- 値の中のダブルクォートは ""(2つ) にしてエスケープする。
例:カンマ入り
name,address
Alice,"Tokyo, Japan"
例:ダブルクォート入り
text
"He said ""Hello""."
4) 文字コード(超重要)
- Webや多くのシステムは UTF-8 が基本。
- Excelでの文字化け対策として、UTF-8に BOM を付ける運用がよくあります(このページのDL/ExportはBOM付き)。
- 相手が Shift_JIS(CP932) を要求するケースもあるので、要件に合わせて変換。
CSVは“ゆるい”形式:
「ルールを守ったCSV」より「相手が読めるCSV」が正解になりがち。
受け入れ側は 区切り推定・BOM除去・列数揃え など防御が大事。
サンプルCSV
このページ配下の ./data/lesson/ に置いてあるサンプルをダウンロードできます。
sample_people.csv(中身)
id,name,email,note
1,Alice,alice@example.com,"Tokyo, Japan"
2,Bob,bob@example.com,"He said ""Hello""."
3,Carol,carol@example.com,"改行入りの例:1行目
2行目(CSVとしては同一セル扱い)"
sample_products.csv(中身)
sku,title,price,tag,description
P-001,USB-C Cable,980,accessory,"1m / 60W / ""fast"""
P-002,Wireless Mouse,2480,device,"Silent click, 2.4GHz"
P-003,Notebook,350,stationery,"A5, ruled, made in Japan"
CSVのエクスポート(PHP例)
配列やDB結果をCSVとして出力してダウンロードさせる基本形。
ポイント:
- Content-Type と Content-Disposition を指定
- Excel向けに UTF-8 BOM を付ける運用も多い
- 値は
fputcsvを使う(クォート/エスケープを任せられる)
<?php
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Disposition: attachment; filename="export.csv"');
// Excel対策でBOM(不要なら削除)
echo "\xEF\xBB\xBF";
$out = fopen('php://output', 'w');
// ヘッダー
fputcsv($out, ['id','name','note']);
// データ(例)
$rows = [
[1, 'Alice', 'Tokyo, Japan'],
[2, 'Bob', "He said \"Hello\"."],
];
foreach ($rows as $r) {
fputcsv($out, $r);
}
fclose($out);
exit;
?>
CSVのインポート(アップロード→プレビュー)
CSVを受け取り、区切り推定・BOM除去・列数揃えをしつつ最大50行プレビューします。
DBに保存する時の考え方(例)
- ヘッダー名でマッピング(例:
email列→users.email) - バリデーション(必須、文字数、型、重複)
- トランザクションで一括投入、失敗時ロールバック
- ログを残す(何行成功/失敗、失敗理由)
補足
- CSVは“仕様がゆるい”ので、受け取り側は防御的に作るのがコツ。
- Excel互換が必要なら、UTF-8 BOM or Shift_JIS を要件で決める。
- 巨大CSVはストリーム処理(1行ずつ)+バッチ投入が安全。
ファイル
./data/lesson/… サンプルCSV./assets/css/styles.css… デザイン./assets/js/main.js… UI(コピー/タブ/ファイル名表示)