CSV 中文乱码,先确认编码
区分文字乱码、分列错误和数字变化,再做有依据的转换。
适用环境:Python 3.10+;示例输入明确为 GB18030 编码的逗号分隔文件
先分清三个不同问题
- 中文变成奇怪字符:可能是读写时使用了不同编码。
- 整行挤在一个单元格:可能是分隔符识别不一致。
- 身份证号、订单号或前导零变化:可能是表格软件把文本自动转成数字。编码转换无法修复这个问题。
已有损坏不一定能转回来
先保留原件,从来源方确认导出编码。不要因为文件能被某个编码解码,就认定它一定正确。若内容已经被替换成问号并保存,原来的字节信息可能丢失;此时需要重新导出原始资料,而不是反复另存。
转换一个已知编码的文件
下面脚本只用于来源明确为 GB18030 的文件。保存为 convert_csv.py,输入名为 input.csv;其他编码请修改 encoding,分隔符不是逗号时也要设置对应 delimiter。
from pathlib import Path
import csv
source = Path('input.csv')
target = Path('output-utf8.csv')
if target.exists():
raise FileExistsError('输出文件已经存在,请先检查或更换名称')
with source.open('r', encoding='gb18030', newline='') as src, target.open('x', encoding='utf-8-sig', newline='') as dst:
reader = csv.reader(src)
writer = csv.writer(dst)
count = 0
for row in reader:
writer.writerow(row)
count += 1
print('已写入记录数(含表头):', count)为什么不用 split 直接拆逗号
CSV 字段本身可以包含逗号、引号和换行。csv.reader / writer 会按规则处理引用字段,避免把地址“上海,浦东”拆成两列。newline 为空交给 CSV 模块处理换行;utf-8-sig 写入标记,便于部分桌面表格软件识别 UTF-8。
转换完成还要验证
检查首尾记录、中文、人名中的少见字和带逗号的字段。代码中的记录数包含表头,且一条记录可能跨多行,因此不能直接用文本行数判断。表格软件导入时,把编号列设为文本;CSV 本身不保存列类型。出错时输出文件可能只写了一部分,不要把存在一个文件当作转换成功。