CSV,也就是 Comma-separated values,是用 逗号 分隔字段值,回车符号分割行的文本文件。比如 example.csv 文件:
它的内部格式是这样的:
aaa, bbb, ccc CRLF
zzz, yyy, xxx CRLF
或者
aaa, bbb, ccc CRLF
zzz, yyy, xxx
本文记录了在处理 csv 文件的时候经常遇到的一些问题及其解决方法。
用引号将带有逗号的值括起来
CSV 的字段值可能会被引号引起来,比如某个字段值是一个有千分位分隔的数字,像这样:
我使用文本编辑器打开这个 csv,可以看到里面就会用 引号 把带有逗号的字段值引起来,没有用逗号分隔的字段值就不会被引号引起来:
反过来试着在文本编辑器中,我们给值的两边加上双引号,用 excel 等软件打开后显示双引号会被去掉不显示。
所以我们在读这种字段值带有逗号的 CSV 文件的时候,就不能单单用逗号去分割字段值了,需要判断有没有引号,如果有引号,就要把配对的引号括起来的值作为整体读成一个字段值,如果用逗号去分割就会把原本一个值读成两个值,还各自外加引号。
怎么精确判断 CSV 文件类型
使用 file.type 判断是不是 CSV 的 MIME type
在上传文件的时候我们需要判断文件类型,以此过滤一些用户上传的不合法的文件,对此,MIME 类型是一种经常使用的方法。浏览器使用 MIME 类型来判断文件格式,以使用相应的方法解析文件,比如 HTML 文件的 MIME 类型是 text/html。
独立的 MIME 类型:
复合文件的 MIME 类型(Multipart 类型):
multipart/form-data multipart/byteranges
由于用于生成 CSV 文件的软件和系统的差异,CSV 格式有着各种实现,也导致读取解析 CSV 文件存在多种方法。不同的平台生成的 CSV 的 MIME 类型有差异,一般情况下,在 Mac 中导出的 CSV 文件读取其 MIME 类型为 text/csv,这也是 RFC4180 中为 CSV 注册的 MIME 类型,但是在 windows 平台的 Execl 导出的 CSV 文件的 MIME 类型是:
application/vnd.ms-excel
由于平台差异包括浏览器的差异,可能出现以下 CSV 的 MIME type:
'text/csv',
'text/plain',
'application/csv',
'text/comma-separated-values',
'application/excel',
'application/vnd.ms-excel',
'application/vnd.msexcel',
'text/anytext',
'application/octet-stream',
'application/txt',
为了兼容 ,需要这样判断 csv 文件类型:
const mimeTypes = [
'text/csv',
'text/plain',
'application/csv',
'text/comma-separated-values',
'application/excel',
'application/vnd.ms-excel',
'application/vnd.msexcel',
'text/anytext',
'application/octet-stream',
'application/txt'
]
const isCsv = mimeTypes.includes(file.type)
值得注意的是,借助文件扩展名来判断文件类型的方法是不可靠的。如果手动修改文件后缀名,然后程序再去根据后缀名判断就错了。
根据 MDN: 除了 MIME type 传送文件类型的方法,还可以使用魔术数字来推断文件类型,就是读取文件结构,根据查看文件头部的十六进制值来区分文件类型。比如 GIF 文件以 47 49 46 38十六进制值开头,更多的文件类型幻数可以看 这里。由于 csv 文件并没有魔术数字,所以不能用这种方法判断 csv 文件类型。
参考
-
RFC4180 :tools.ietf.org/html/rfc418…