打开 Excel 就能瞅见?
其实纯文本里藏着“无数据库·轻量级数据协议”的大能量!
今天 10 分钟,带你拆透 CSV 的格式规则 → 编码陷阱 → 高速读写 → 实战技巧🔧
1️⃣ 什么是 CSV?🤔
- Comma-Separated Values
- 纯文本:任意编辑器都能改,Excel/GSheet 默认打开📊
- 一行 = 一条记录,逗号分隔列,换行分隔行
- 无数据类型 → 全!部!是!字!符!串!(读的时候再 cast)
2️⃣ 格式细则:3 条就能写解析器📜
| 规则 | 正确示范 | 错误示范 |
|---|---|---|
| 分隔符 | 逗号 , | 分号 ;(区域设定) |
| 换行 | \n 或 \r\n | 混合换行会炸 |
| 引号包裹 | "New York, USA" | 直接写逗号→被当成两列 |
| 引号转义 | 双引号 "" | 单反斜杠 \ 不认 |
完整官方描述:RFC 4180(记住编号,面试能吹🎺)
3️⃣ 编码地雷:打开乱码 99% 是它💣
| 系统/软件 | 默认编码 | 解决方案 |
|---|---|---|
| Windows 简体 | GB18030 | 保存时选 UTF-8 with BOM |
| Excel 2016+ | UTF-8 BOM | 无 BOM 会中文乱码 |
| macOS/Linux | UTF-8 无 BOM | iconv -f gbk -t utf8 old.csv > new.csv |
口诀:**“跨平台先 UTF-8,带 BOM 保平安”**🌍
4️⃣ 不用库:手搓最简读写(30 行)🖐️
# 最简读
with open('data.csv', encoding='utf-8') as f:
header = f.readline().strip().split(',')
for line in f:
row = line.strip().split(',')
print(dict(zip(header, row)))
# 最简写
rows = [['id', 'name'], ['1', 'Alice'], ['2', 'Bob']]
with open('out.csv', 'w', encoding='utf-8') as f:
for r in rows:
f.write(','.join(r) + '\n')
结论:能跑,但引号/转义/换行全没处理 → 生产环境请用标准库🙅♂️
5️⃣ 标准库 csv:官方认证,功能全✅
import csv
# 读
with open('data.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f) # 或 csv.DictReader(f)
for row in reader:
print(row) # row 是列表
# 写
with open('out.csv', 'w', newline='', encoding='utf-8') as f:
writer = csv.writer(f)
writer.writerow(['id', 'sales'])
writer.writerows([[1, 100], [2, 200]])
参数大全
delimiter=';' quotechar='"' quoting=csv.QUOTE_MINIMAL
6️⃣ Pandas 极速读写:一行搞定💡
import pandas as pd
df = pd.read_csv('data.csv', # 文件/URL 都行
encoding='utf-8',
parse_dates=['订单日期'], # 直接转日期
dtype={'客户ID': 'string'}, # 指定类型
na_values=['', 'NULL']) # 识别空值
# 写
df.to_csv('out.csv', index=False, encoding='utf-8-sig') # BOM+UTF-8
- chunksize=1e5 → 分块读大文件(百万行无压力)
- engine='pyarrow' → 多线程,2-5 倍提速🏃♂️
7️⃣ 大文件场景:三种姿势对比🚄
| 方案 | 代码片段 | 内存占用 | 速度 |
|---|---|---|---|
| 一次性 read_csv() | pd.read_csv(file) | 高 | 最快 |
| 分块 iterator | for chunk in pd.read_csv(file, chunksize=1e5): | 中 | 中 |
| 流式 csv.reader | 标准库 reader | 低 | 慢 |
结论:<= 1 GB 直接 pandas,> 5 GB 上 chunksize / Dask☁️
8️⃣ Excel <–> CSV 互转:一键 CLI🔄
# 多条 sheet 转多个 csv
libreoffice --headless --convert-to csv:"Text - txt - csv" *.xlsx
# csv 合并到多 sheet(需 Python)
with pd.ExcelWriter('merged.xlsx') as writer:
for csv in Path('.').glob('*.csv'):
pd.read_csv(csv).to_excel(writer, sheet_name=csv.stem, index=False)
9️⃣ 常见坑 & 排查清单🕳️
| 现象 | 原因 | 快修 |
|---|---|---|
| 中文乱码 | 编码不对 | 用 encoding='utf-8-sig' |
| 科学计数法 | 大数字被 Excel 改 | df.to_csv(..., float_format='%.0f') |
| 日期被截 | 没指定 parse_dates | read_csv(..., parse_dates=['日期列']) |
| 分隔符识别错 | 区域设定 | read_csv(..., sep=';') |
🔟 进阶:CSV 不是终点🚀
- CSV → SQLite:
.mode csv+.import file.csv table - CSV → Parquet:
df.to_parquet('out.parquet')体积↓50%,速度↑3 倍 - CSV → JSON:
df.to_json(orient='records', lines=True)给 Mongo/ES 喂数据
🏁 一句话总结(背它!)
**“CSV = 纯文本表格,UTF-8 防乱码,引号包逗号,读用 pandas,大文件 chunksize,写完带 BOM 跨平台稳!”**📌