CSV 大概是数据格式里最简单的那一种。它是纯文本,一行一条记录,值用逗号分开:
name,quantity,priceWidget,12,4.50
整个概念就是这样,而这正是 CSV 活得比每一个想取代它的封闭格式都久的原因。每个程序都读得了它、它很小、它在任何文本编辑器里都打得开,而且你可以确切看到里面有什么。
它同时也是最可能在不告诉你的情况下损毁你数据的格式,而那些理由值得在你下次打开一个 CSV 之前就知道。
这一点一直在坑人,而且它是语言问题,不是软件 bug。
在德文、法文、西班牙文、葡萄牙文和许多其他语系里,逗号是小数点——4,50 是四点五。那逗号就不能同时拿来分隔字段,所以那些语系的电子表格软件改用分号来写、也预期读到分号:
name;quantity;priceWidget;12;4,50
两个文件都叫 CSV。把分号版本拿去用逗号的程序开,每一行都会塌成单一列。把逗号版本拿去用分号的程序开,同样的事反过来发生一次。
文件里没有任何标记说明它是哪一种。唯一可靠的解法是用导入而不是点两下,这样你可以自己指定分隔符。
如果一个值里面本来就有逗号怎么办?它会被包在双引号里:
"Smith, John",12,4.50
而当一个值里有引号,那个引号会写成两个来转义。一个字段甚至可以含有换行,只要它有被引号包住——这就是为什么你不能靠数 CSV 的行数来可靠地算出有几条记录。
每一个正规的 CSV 工具都处理得了这些。手工拼出来的文件——任何用逗号把字符串接起来做出来的东西——通常处理不了,而破绽只会在某人的名字或地址刚好含有逗号的时候才出现。
这是这个格式最具破坏力的缺口,而且没有好的答案。
一个 CSV 文件不含任何关于它字符编码的声明。不像 HTML 或 XML,它没有地方可以说“这是 UTF-8”。打开它的程序只能猜。
Windows 上的 Excel 传统上猜的是系统的本地代码页而不是 UTF-8。所以一个含有中文、日文或韩文——或者带重音的欧洲字符——的 CSV,开起来是一堆读不懂的符号,即使那个文件完全正确。
两个实务上的应对:
这是真正让人付出代价的部分,因为它是无声的,而且在你还没做任何事之前就发生了。
CSV 没有类型——每一个值都是文本。电子表格会猜每一个值是什么意思,而它的猜测在几种反复出现的情况下,自信地错着:
01234 变成 1234。电话号码、账号、产品编号和身份证号全都遭殃。1.23457E+15 的东西,而原本的数字是没了,不是被藏起来。3-10 的值变成 10 月 3 日。这就是那个著名的问题,逼得遗传学家把一些名称老是被转成日期的基因重新命名。关键细节:如果你接着保存,损害就被写回去了。原本的值无法从保存后的副本救回来。
两个习惯能防掉全部。任何你收到的 CSV,留一份没碰过的副本。而当内容包含编号、标识符或任何开头有零的东西时,走导入路线,并且在数据落地之前把那些列标记成文本。
而它做不到的:多个工作表、公式、格式、单元格类型、合并单元格、图表,或任何嵌套结构。那些正是电子表格格式和它并存的理由。