3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

あなたのCSVが会社を潰す日 〜非エンジニアが知らずにやらかすWindowsの罠〜

Posted at

CSV×改行コード(CRLF/LF)で二度と死なない:Excel/Windows産CSVをLinuxサーバへ安全に流し込む実戦手引き

結論

Windowsで作ったCSVをそのまま渡すと、相手(サーバやDB、エンジニアのスクリプト)側で行の区切りがズレて「カラム数が合わない」「文字化け」「取り込み失敗」などが起こります。対策は (1) 改行のそろえ(EOL統一)(2) "CSVとして"正しく読み込むこと の二本柱。この記事の手順をコピペすれば回避できます。


これは"非エンジニアのあなた"に起きがちな事故です

  • 「私がExcelで作ったデータで夜中にシステムが止まった」
  • 「売上レポートが文字化けして、役員会議が延期になった」
  • 「顧客リストの取り込みが失敗して、メール配信が止まった」

実はこれ、あなたの作業が悪いわけではありませんWindowsの改行のしかたCSVのルールの"ちょっとしたズレ"が原因の環境差のせいです。でも、知らないとヤバいことになります。


実録:非エンジニアが引き起こした大事故(5選)

1. 「売上データが消えた」月末の地獄絵図

登場人物:営業企画のAさん(Excel大好き、IT知識ゼロ)

状況:毎月末、全国の売上データをExcelで整理してシステムに一括アップロード。今月は過去最高売上を記録し、役員も大注目。

事件発生:いつも通りCSVで書き出してアップロード→「処理中...」のまま3時間固まる→全データが中途半端に取り込まれて売上が半分以下に表示

大混乱

  • 役員「売上半減?!何があった?!」
  • 営業部長「システム障害ですか?」
  • 情シス緊急招集→夜中の3時まで復旧作業
  • 翌朝の役員会議は「データ信頼性の問題」で大炎上

真犯人:Aさんが見やすさのために住所欄で**Alt+Enter(セル内改行)**を多用→CSV出力時に引用符が一部外れて行がバラバラに→取り込み処理が暴走

Aさんの心境:「私、何か悪いことした...?普通にExcelで整理しただけなのに...会社に迷惑かけちゃった...」


2. 「顧客に間違った人の個人情報を送信」プライバシー大事故

登場人物:マーケティング部のBさん(キャンペーン担当、几帳面)

状況:新商品キャンペーンで1万人にパーソナライズメールを送信予定。顧客データベースからExportしたCSVに、手作業で「特別オファー金額」を追加して一括処理。

事件発生:配信開始30分後、お客様相談室に電話が殺到

悲劇の内容

  • 田中さんに「佐藤様、あなたの年収1200万円に相応しい...」
  • 佐藤さんに「山田様、シングルマザーのあなたを応援...」
  • 山田さんに「鈴木様、ご主人の定年後の資産形成...」

原因:顧客名の一部に**会社名(改行付き)**が含まれていた→CSV処理でデータがズレて個人情報が完全に入れ替わり

その後

  • 謝罪対応に1週間、法務部も巻き込んで大騒動
  • 個人情報保護委員会への報告書作成
  • Bさん、責任を感じて体調不良で1ヶ月休職

Bさんの証言:「まさか自分がデータを作っただけで、お客様にご迷惑をかけるなんて...もうExcelが怖くて触れない」


3. 「給与計算が狂って全社員に間違った給与を支給」

登場人物:人事部のCさん(勤続15年のベテラン)

状況:働き方改革で在宅勤務手当や時差出勤手当が新設→給与システムが対応していないため、手当部分だけExcelで管理してCSVで給与システムに追加取り込み

大惨事:給与支給日の朝、全社員500人の銀行口座に給与振り込み完了→新入社員が部長より高給取りに、部長の給与が最低賃金以下に

阿鼻叫喚

  • 新入社員D君「えっ、僕の給料80万円?間違いですよね?」
  • 部長「俺の給料8万円って...バイト以下じゃないか!」
  • 経理「銀行への振り込み取り消しは不可能です」
  • 社長「信用問題になる、すぐ何とかしろ!」

原因:手当CSV内のコメント欄に改行を含む「業務内容詳細」を記載→取り込み時にデータがずれて、社員番号と金額がバラバラに対応

後処理

  • 全員に謝罪と訂正振り込み(2日後)
  • 労基署から「賃金支払いの不備」として指導
  • Cさん「15年間ミスしたことなかったのに...」

4. 「株主総会資料の数字が全部デタラメ」

登場人物:IR担当のEさん(数字に強い、責任感強すぎ)

状況:上場企業の四半期決算発表前日、最終チェックのため会計データをExcelで整理→投資家向け資料に使う重要指標をCSV出力

絶望的展開:翌日の決算説明会で、売上成長率が-95%、営業利益率が400% などの異常数値を堂々と発表

会場の様子

  • 投資家A「売上がほぼゼロ?倒産するんですか?」
  • 投資家B「利益率400%って...粉飾決算ですか?」
  • アナリスト「こんなデタラメな数字、初めて見た」
  • 株価、決算発表直後に30%暴落

真相:財務データの「前年同期比」列に改行付きコメント(「※為替影響考慮\n実質成長率は...」)が混入→CSV処理で数値列がコメント列とずれて、とんでもない計算結果に

Eさんのその後:「会社の株価を暴落させた女」として社内で有名に→転職を決意


5. 💀「薬事法違反で業務停止命令」製薬会社の悪夢

登場人物:品質管理部のFさん(薬学修士、超真面目)

状況:新薬の臨床試験データをExcelで管理→承認申請用にCSVで厚労省システムへ提出

致命的ミス:データ取り込み時に患者の症状記録が別の患者と入れ替わり→「重篤な副作用なし」の患者が「重篤な副作用あり」として申請

発覚と大惨事

  • 承認審査中に厚労省が異常を発見
  • 「臨床データの信頼性に重大な疑義」として審査中止
  • 業界紙一面「○○製薬、データ改ざん疑惑」
  • 株価50%下落、業務停止命令3ヶ月
  • 新薬開発費100億円が水の泡

Fさんの告白:「患者さんの命に関わるデータなのに...私の手でこんなことになるなんて。一生償いきれない」

原因:症状記録に改行付きの長文があったが、CSV出力時の引用処理が不完全→患者IDと症状データの対応が崩壊


あなたも明日やらかすかもしれない理由

これらの事故、**全て「普通にExcelを使っただけ」**で起きています。

  • Windowsで普通にExcelを使う
  • 見やすくするためにセル内で改行(Alt+Enter)
  • CSV保存してシステムに渡す

この当たり前の流れで大事故が起きるのが現実です。

しかも**「昨日まで正常だったのに今日だけ異常」**というパターンが多く、原因究明まで時間がかかって被害が拡大します。

「私は単純なデータしか扱わないから大丈夫」 ←これが一番危険。気づかないうちに改行やコメントが紛れ込んで、いつか必ず事故ります。


なにが起きているの?(やさしい説明)

  • 改行の記号がOSで違う

    • Windowsは行の終わりに CRLF(2文字)
    • macOS/Linuxは LF(1文字)
  • CSVはルールがある

    • セルの中に改行があってもOK(ただし**"で囲む**必要あり)
    • "(ダブルクォート)自体が入るときは "" と二重に

エンジニア側の取り込み(サーバ/DB/スクリプト)がこれらを**“文字通りCSVとして”扱っていない**と、行が途中で切れたり、見えない文字(
)が混ざって数値にできなかったりします。

macなら大丈夫? いいえ。Excel for Macが出すCSVでも、Windows式の改行やBOMが入ることがあり、同じ事故が起きます。


あなたができる安全対策(コピペでOK)

  • 渡す前に“改行をそろえる”(CRLF→LF)
  • 取り込み側は“CSVとして読む”(行分割ではなく、CSVモード/専用パーサを使ってもらう)

この記事には、

  • 前処理のコピペ用コマンド(Windows/ Mac /Linux)
  • DB取り込みの正しい設定例(PostgreSQL / MySQL)
  • 壊れやすいパターンのチェック方法
    をまとめました。仕組みはあと回しでも、手順だけ真似すれば事故は止まります。

想定読者

  • Windowsで出力したCSVを Linux/macOSサーバ のDBに取り込む人
  • Excel/業務システムが吐くCSVで取り込みが不安定な現場
  • CSVパースを自作していて“行数/カラム数が合わない”系の不具合に悩む人

この記事のゴール

  • 改行コードとCSV仕様の要点を 実務目線 で整理
  • 再発防止テンプレ(前処理ワンライナー/DB取り込みレシピ/CIチェック)を配布

まず用語整理:EOL(改行コード)の違い

OS 記号 実体
Windows CRLF \r\n
macOS / Linux / Unix LF \n
  • エディタや簡易スクリプトが \n だけでsplit すると、末尾に \r が残って "\rOK" のようなゴミ文字化→数値変換エラー、JOINミスなどに波及。
  • ExcelのCSVプラットフォームを問わずCRLF を出すケースが多い(Excel for Macでも)。

CSVの“正解”挙動(RFC 4180 要旨)

  • 改行やカンマを含むフィールドは 二重引用符 " で囲む
  • フィールド内の二重引用符は "" と二重化 してエスケープ
  • 行の区切りは原則レコード境界(=EOL)。引用符で囲まれたフィールド内のEOLは1セル内の文字列として扱われる

つまり、フィールド内改行はOK。ダメなのは 引用なしで生改行が入っているCSVEOLと引用の混在・不整合


よくある症状

  • 取り込みツールで カラム数が合わない(途中で行が切れてしまう)
  • 数値列やフラグ列に \r が混入 して cast エラー
  • 先頭カラム名に BOM(\uFEFF) が混入→カラム名不一致

まずは現物診断(安全な読み方)

# CR(\r) を含む行を検出(^M表示)
grep -n $'\r' file.csv | head

# 引用符の不整合(簡易チェック:行ごとの '"' 出現数が奇数なら怪しい)
awk -F '"' '{if ((NF-1)%2==1) print "unbalanced at line", NR}' file.csv | head

# 文字コード/BOMの確認
file -I file.csv     # application/csv; charset=utf-8 など
xxd -g 1 -l 3 file.csv  # 先頭が EF BB BF なら UTF-8 BOM

前処理テンプレ:EOL正規化(LF統一)

Linux/WSL/macOS 共通

# 破壊的にCR削除(CRLF→LF)
sed -i '' -e 's/\r$//' file.csv  # macOS(BSD sed)
# Linuxなら: sed -i 's/\r$//' file.csv

# 非破壊で出力を分けたい場合
tr -d '\r' < file.csv > file_lf.csv

# 専用ツール(Homebrewで入る)
dos2unix file.csv

Windows PowerShell

(Get-Content file.csv -Raw) -replace "`r`n","`n" |
  Set-Content file.csv -NoNewline -Encoding utf8

ポイント: 中身をCSVとして壊さない。EOL正規化はOKだが、カンマや引用の置換は厳禁


DB取り込みの“正しい姿”

PostgreSQL

COPY mytable(col1, col2, ...)
FROM '/path/file.csv'
WITH (
  FORMAT csv,
  HEADER true,
  DELIMITER ',',
  QUOTE '"',
  ESCAPE '"'
);
  • FORMAT csv を使う限り、引用付きフィールド内改行も扱える。CRLF/LFはどちらも処理可。

MySQL / MariaDB

LOAD DATA INFILE '/path/file.csv'
INTO TABLE mytable
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"'
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;
  • Windows由来なら LINES TERMINATED BY '\r\n' を明示。LFに正規化した場合は \n を指定。

SQLite(補足)

.mode csv
.import file.csv mytable
  • 混在EOLは不安定。事前にLFへ正規化が無難。

アプリ側の“壊れない読み方”

Python(標準csv)

import csv
with open('file.csv', newline='', encoding='utf-8') as f:
    reader = csv.reader(f)  # 引用・改行を仕様通りに処理
    for row in reader:
        ...

pandas

import pandas as pd
df = pd.read_csv('file.csv', dtype=str, keep_default_na=False)

Node.js(例:csv-parse)

import { parse } from 'csv-parse'
import fs from 'node:fs'

fs.createReadStream('file.csv')
  .pipe(parse({
    columns: true,
    relax_quotes: false,
    relax_column_count: false
  }))
  .on('data', r => { /* ... */ })

Go

r := csv.NewReader(file)
r.LazyQuotes = false // 仕様に厳格
records, err := r.ReadAll()

重要:readlines() で行を split しない。必ず CSV パーサに任せる。


エディタ & Git の地雷回避

VS Code

  • 右下の End of LineLF に変更
  • 設定例:
{
  "files.eol": "\n",
  "editor.renderControlCharacters": true
}

Git

git config --global core.autocrlf input   # macOS/Linux
# WindowsでLF維持したい場合も 'input' を推奨

.gitattributes でCSVだけLFを強制:

*.csv text eol=lf

BOM/文字コードの取り扱い

  • 先頭に UTF-8 BOM があると、ヘッダ名に不可視文字が混入 → カラム不一致
  • 事前に除去:
# 先頭3バイトのBOMを剥がす(非破壊)
tail -c +4 file.csv > file_nobom.csv
  • もしくは iconv で再エンコード:
iconv -f utf-8 -t utf-8 file.csv -o file_nobom.csv

実戦レシピ:ワンショット取り込み

set -euo pipefail
in="file.csv"
out="/tmp/file.lf.csv"

# 1) EOLをLFに正規化
tr -d '\r' < "$in" > "$out"

# 2) 構造チェック
csvclean -n "$out" || { echo "CSV structure looks suspicious"; exit 1; }

# 3) PostgreSQLへ(例)
psql -v ON_ERROR_STOP=1 -c "\
  COPY mytable(col1,col2,...) FROM '$out' \
  WITH (FORMAT csv, HEADER true, DELIMITER ',', QUOTE '"', ESCAPE '"');"

CIでの再発防止(プリチェック)

pre-commitフック例

#!/usr/bin/env bash
set -euo pipefail
bad=$(grep -IlR $'\r' -- '*.csv' || true)
if [ -n "$bad" ]; then
  echo "[EOL] CRLF detected in:"; echo "$bad"; exit 1
fi
# 引用不整合の簡易検査
echo "$@" | xargs -r -n1 awk -F '"' '{if ((NF-1)%2==1) {print FILENAME ": line" NR " has unbalanced quotes"; exit 1}}'

.gitattributes も併用:

*.csv text eol=lf

FAQ

Q. macOSはUNIX系だから問題にならない?
A. No。特定条件下でだめ。macOS自体はLFだが、たとえばExcel for MacWindows生成のCSV を扱うと CRLFやBOM混入 で同様に破綻する。取り込み先がLinuxでもmacOSでも、前処理と正しいローダ が必要。

Q. フィールド内改行は全部排除すべき?
A. 仕様的にはOK。どうしても運用上NGなら、書き出し側で改行→\n 等に変換し、読み込み時に復元するポリシーを決める(要合意)。

Q. 自作パーサを直せばよい?
A. 原則おすすめしない。パーサは既存実装(DBのCSVモード、言語標準、実績ライブラリ)を使う。


2. 「ヘッダが見つからない」BOMの罠

状況:マーケがExcelで出したCSVをpandasで読み、PostgreSQLへCOPY。なぜか列名idが見つからない。

症状KeyError: 'id' / DB側では column "id" does not exist

原因:CSV先頭にUTF-8 BOM() が付与。ヘッダが実際は id,name,... になっており一致せず。

再現の断片

EF BB BF 69 64 2C 6E 61 6D 65 ...  # バイト列先頭がEF BB BF

対処

  • 事前に tail -c +4 でBOM除去、または iconv 再エンコード
  • pandas側は encoding='utf-8-sig' で読み込み、DB投入前に明示的にカラム名を正規化

学びBOMは“見えない敵”。ヘッダ不一致やカラム名の取り違えはBOMを疑う。


3. 「OK

」で判定バグ—CRの居残り
状況:社内ツール(Python)が 区切りで行をsplitしてCSVを読んでいた。Windows発のCSVに切り替えた日から判定が不安定に。

症状status == 'OK' のはずがFalse判定、数値カラムのint('100 ')で例外。

原因:WindowsのCRLF行末を だけで分割したため、末尾の が値に残留。

再現の断片

for line in open('w.csv').read().split('
'):
    cols = line.split(',')
    status = cols[-1]
    # 'OK
' になっていて比較に失敗

対処

  • 入力前に CR除去(CRLF→LF)
  • そもそも csvモジュールDBのCSVモード を使う(行splitをやめる)

学び「行で割る」は事故の元。CSVはCSVとして読む。EOLは最初に正規化。


まとめ(チェックリスト)

  • EOL統一(CRLF→LF)
  • UTF-8/BOM除去
  • CSVローダ/パーサ利用(行split禁止)
  • 引用とエスケープ"..." & ""
  • DB側オプション適合FORMAT csv/LINES TERMINATED BY
  • CI/フックで検知

付録:最小再現データ

id,name,comment
1,"Alice","Hello\nWorld"
2,Bob,"He said ""Yes"""
3,Carol,
  • これを CRLF にして、素朴な split('\n') 実装 に食わせると破綻する。DBのCSVモードや言語のCSVパーサなら正しく解釈できる。

ライセンス

  • 本記事のコード片は MIT とします。業務ドキュメントやPlaybookへの転用可。
3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?