CSV是一种常见的文件格式,常用于不同系统之间的数据交换,对于该文件格式可以简单描述为:一组使用逗号“,”分隔字段,并以换行符作为一行数据结束的数据集合。该文件可以使用Microsoft Excel查看,但是中文字符会显示为乱码。
这个描述就真的只是简单描述,实际上CSV的格式处理没有这么简单。最近在和另外一个系统做集成,我们的系统会提供CSV数据文件给对方系统处理,由于我们系统中个别字段会包括换行符“CRLF”(这是遗留系统,就不用纠结为什么字段中会包含换行符了),也就是说一个字段可能会显示在几行上,但是这个字段是包含在双引号中的,结果对方系统就处理不了了。因为对方系统只是简单的按行处理数据,用逗号解析字段。
这种解析方式通常是没有问题,但是是不完整的。RFC 4180是CSV格式的标准,这里提到并没有官方的规范去定义CSV的格式到底是怎样的,但是根据大多数的实现来看,应该有如下格式:
每条数据用换行符(CRLF)分割。
最后一条数据可以不包含换行符。
可选的header行,如有的话,应该出现在第一行,并且与下面的数据有相同数量的字段。
在header和每条数据中,使用逗号“,”分隔字段,每一行都应该包含相同数量的字段,空白字符也可作为一个字段,一条数据的最后一个字段不应添加逗号分隔符。
每个字段可以包含在双引号中。
如果字段中包含换行符(CRLF),双引号和逗号,则必须将字段包含在双引号中。
如果字段中包含双引号,则除了需要将字段包含在双引号中,还要在字段中的双引号前再加一个双引号作为转义。
由此可见,字段中是允许出现换行符的,只要该字段是包含在双引号中的。我也查阅了Spring Batch的CSV Reader的实现,也考虑到了该问题,在发现换行符的同时,也会检查当前字段是否已结束。
因此,我们在生成或解析CSV文件时,应该要考虑到以上特殊字符的处理,在apache的common-lang包中,也有专门针对CSV字符的转义方法,可参考StringEscapeUtils,在最大程度上保证系统的robust。