为什么Excel会弄坏您的CSV
邮政编码丢了开头的0,产品编号变成了日期,长长的编号被悄悄四舍五入。问题发生在打开时,而不是保存时——所以很多人始终弄不清到底哪里出了错。
最后审阅:
损坏发生在打开的那一刻
这正是这个问题难以诊断的原因。CSV是文本文件:其中每个值都只是字符,文件里没有任何信息说明它们代表什么。Excel打开CSV时,会为每一列猜测一种类型,把值转换成对应的类型,并从此只保留转换后的版本。一旦保存,这些转换就会被写回文件。
于是,原文件没有问题,您保存的文件却出了问题,而整个过程中没有任何提示。人们以为是导出坏了,于是重新导出,结果还是一样——因为损坏是在下载之后、在他们自己的电脑上发生的。
造成损坏的四种转换
开头的0被删掉。 以0开头的邮政编码、法国的省份代码、账号、以0开头的电话号码——这些看起来都像数字,于是开头的0被当作无意义的数字丢弃。但它并非无意义,而是编号的一部分。
长数字被四舍五入。 电子表格以浮点数存储数字,有效数字只有大约十五位,所以订单号、信用卡号、IMEI或64位编号会被悄悄四舍五入——最后几位变成0。单元格看起来是个数字,却是个错误的数字。
任何像日期的内容都会被重新格式化,而且按照本地习惯。03/05在一个国家表示3月,在另一个国家表示5月,所以同一个文件在两个办公室打开,会得到两份不同的数据。更糟的是,本来就不是日期的值也会被转换:像SEPT1这样的基因名会变成日期,这个问题顽固到遗传学家最终干脆给这些基因改了名,而不是继续和它较劲。
带重音的字符变成乱码。 CSV不会记录自己的字符编码,所以按UTF-8保存的文件如果被当作旧式代码页读取——或者反过来——恰恰是那些包含带重音姓名的行会被弄乱。
解决方法:导入,而不是打开
重要的CSV文件,千万不要双击打开。 双击等于允许Excel去猜,而它猜得非常自信。
请改用数据 → 从文本/CSV。导入对话框允许您在解析之前设置每一列的类型——把邮政编码列和编号列设为文本,它们就会原封不动地按文件里的样子导入。它还允许您直接指定编码和分隔符,而不是由程序推断。只需二十秒,问题就彻底解决了。
Google表格同理:选择“文件 → 导入”,并关闭“将文本转换为数字、日期和公式”。LibreOffice Calc默认就会显示列类型对话框,这是它少有的、单纯表现更好的地方之一。
导入之前先检查
如果已经出了问题,第一步最好是在不让电子表格碰它的情况下查看文件。查看CSV会按字节的本来面目显示各个值——开头的0还在,长数字完整,日期保持写入时的文本。这能让您立刻判断出错的是导出还是导入。
它还会显示CSV从不自我说明的两件事:分隔符——逗号、分号还是制表符(欧洲地区导出时常用分号,因为逗号是他们的小数点)——以及编码。导入前弄清这两点,剩下的猜测基本就消除了。
如果CSV是由您生成的
在导出端做好几个决定,就能在下游避免上述所有问题。
如果文件要在Windows上用Excel打开,请写入带字节顺序标记(BOM)的UTF-8。Excel靠这个标记识别UTF-8,没有它就会把带重音的字符弄乱——这是少有的、添加BOM是正确选择而非麻烦的情况之一。
凡是可能被误读的字段都加上引号,编号列则一律加引号。加引号并不能阻止Excel在打开时转换,但能让其他所有读取方都清楚明白您的意图。
考虑干脆不用CSV。 如果对方能接收JSON或真正的电子表格,这两种格式都会明确记录类型,也都不存在上述任何问题。CSV的优点是什么都能读取它,缺点是谁都无法就它的含义达成一致。
常见问题
保存之后还能撤销损坏吗?
无法可靠地撤销。被删掉的开头的0和被四舍五入的数字已经没了——文件里没有任何东西可以用来恢复。请从原始数据源重新导出;这也是为什么原始导出文件值得占用磁盘空间、原样保留。
为什么我的CSV打开后只有一长列?
分隔符和电子表格预期的不一致——通常是用分号分隔的文件在使用逗号的地区设置下打开,或者反过来。导入对话框可以让您直接指定分隔符,这比修改系统的区域设置更快。
第一列列名开头那个奇怪的字符是什么?
是字节顺序标记(BOM),被当成了文本而不是编码提示来读取。它正是能让Excel正确显示带重音字符的那个标记,所以它既有用又恼人——大多数规范的CSV解析器会自动去掉它。
CSV有标准吗?
只有一份2005年的建议性规范,描述了大多数工具的做法,而仍有大量软件另行其是。这就是为什么分隔符、引号、换行符和编码都各不相同——也是为什么在真实文件上唯一可行的方法是检测它们,而不是假定它们。
为什么在文本编辑器里一行会被分成好几行?
因为加了引号的字段可以合法地包含换行——通常是地址字段。这条记录仍然是一行;任何按换行符拆分文件的程序,都会恰好弄坏这些行,所以按逗号或换行符拆分并不是读取CSV的正确方法。