技术分享讲清原理,动手验证
返回教程列表

CSV 中文乱码,先确认编码

文件与脚本 · 更新于 2026年10月26日

区分文字乱码、分列错误和数字变化,再做有依据的转换。

适用环境: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 本身不保存列类型。出错时输出文件可能只写了一部分,不要把存在一个文件当作转换成功。

下载本文脚本:convert_csv.py

官方参考资料

下列资料用于核对工具行为和参数,文中的示例由本站整理。

相关教程