你可能想不到,我也是想不到,到现在还有人不知道什么是CSV格式的文本数据。最关键的是,不知道的人并不认为自己不知道,这就尴尬了···大家都认为自己知道,但是确实这个认知是有差异的。
某项目咨询我一个问题:“CSV格式的文本数据,Dataworks的数据集成有问题,总报错。该怎么办?”我立即就反驳了:“我这么多年怎么从未遇到过,我们好多项目正在大规模的使用,从未反馈过这类问题啊?”于是我意识到一个问题:这个CSV格式估计不是标准的CSV格式,而是自以为的CSV格式。
或者常有这种说法“我提供了Excel文件,为什么导入不了?”,把csv文件默认为就是Excel文件。而当我提醒对方:“这是两种不同的文件类型,Excel是Office办公软件的一种特有的二进制文件格式,而CSV格式是一种文本格式的数据格式。”。又会陷入另外一个困境,就是:“为什么Excel不是一个文本格式?什么是文本格式?”。总的来说太难了,这也是我不得已写这篇文章的原因。虽然我感觉我可能很努力,也可能还是没办法讲的很清楚。
1-Excel与CSV
什么是 .csv 文件?
CSV 文件是一种简单类型的纯文本文件,它使用特定的结构来排列表格数据。CSV 文件的标准格式由行和列数据定义(行和列构成了一个二维表格),其中换行符终止每一行以开始下一行,并且每一列在行内用逗号分隔。CSV文件中的某一个值文本中如果包含逗号、换行符、双引号则需要用2个双引号把这个值包含起来,如果这里还包含双引号,则需要在每个值中的双引号前面加一个双引号进行转义。(这里提到的字符,都指ASCII字符,而不是中文字符)
什么是 纯文本文件?
个人认为纯文本文件这个概念,就是在windows/linux操作系统上用文本编辑器可以直接打开阅读的,并且这些文本没有任何格式(比如字号、颜色等任何修饰),官方解释可以在“参考”章节查看“纯文本文档”。
什么是 Excel 文件?
Microsoft Excel 是 Microsoft 办公套件中包含的电子表格软件。它广泛用于创建指定计算、库存跟踪、会计等的数字和公式的表格和网格。
CSV与Excel的对比
Excel |
CSV |
Excel 是一种电子表格,可将文件保存为自己的专有格式,即 xls 或 xlsx |
CSV 是一种将表格信息保存到扩展名为 .csv 的逗号分隔文本文件中的格式 |
Excel 二进制文件文件只能用电子表格软件或者支持Excel的软件打开 |
CSV 是一种纯文本文件,可以使用任何文本编辑器打开,例如记事本、vi、word、Excel等。 |
Excel不仅可以存储数据,还可以对数据进行操作 |
CSV 是一个文本文件,它存储数据但不包含格式、公式、宏等。它也称为平面文件 |
除了文本,数据还可以以图表和图形的形式存储 |
无 |
Excel 可以连接到外部数据源以获取数据。您可以在 Excel 中使用自定义加载项来增加其功能。Excel 允许通过详细的跟踪和评论功能查看数据。 |
无 |
任何解析 Excel 数据的编程语言库通常都较大、较慢且复杂 |
解析 CSV 数据的任何编程语言都是微不足道的,生成它非常容易 |
Excel 在导入数据时消耗更多内存 |
导入 CSV 文件可以更快,而且消耗的内存也更少 |
通过上面的对比,我们可以看到CSV文件与Excel文件是2种完全不同的文件类型。Excel文件是一种复杂的二进制文档格式,可以包含很多高级能力,而CSV文件只是一种纯平面的文本文件。
2-CSV格式标准
在上一节中我对CSV文件有了一个定义,这个定义比通常描述的逗号分隔的文本文件要丰富一些。如下:
1-文件类型。CSV文件是一种简单类型的纯文本文件,它使用特定的结构来排列表格数据。
2-分隔符。CSV 文件的标准格式由行和列数据定义(行和列构成了一个二维表格),其中换行符终止每一行以开始下一行,并且每一列在行内用逗号分隔。
3-文本边界与转义。CSV文件中的某一个值文本中如果包含逗号、换行符、双引号则需要用2个双引号把这个值包含起来,如果这里还包含双引号,则需要在每个值中的双引号前面加一个双引号进行转义。(这里提到的字符,都指ASCII字符,而不是中文字符)
4-编码与换行符。CSV文件没有明确定义字符编码与换行符,也就是说任何字符编码都可以被使用,不管是Windows还是linux、unix、Mac换行符都是可以用的。只要保存与打开的时候保持一致即可。
这个CSV文件的定义是我从各种文档中总结整理出来的,显然并不是那么全。一定有遗失和不完全的地方,这就需要标准。很快我也找到了关于CSV的标准:RFC4180、RFC7111。
什么是RFC4180文件格式?【https://www.rfc-editor.org/rfc/rfc4180.html】
RFC4180是一种规范,定义了一种常见的CSV文件格式。根据这个规范,CSV文件由多个行组成,每行由逗号分隔的字段组成。字段可以包含文本、数字或日期等数据。在RFC4180规范中,字段中的文本可以包含引号,并使用双引号进行转义。这意味着如果字段中包含逗号或双引号,可以使用双引号将其括起来。
与我们场景的IEEE/ISO标准或者GBT标准不同,Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多在标准内的论题,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中。
关于CSV的标准有2个,主要是RFC4180,作为补充的是RFC7111。我本来希望好好阅读一下,不过真是看着困难。看了半天该如何读懂RFC文件的文档,感觉有点浪费时间,索性下面就用Excel这个CSV标准的实践来了解。
3-CSV格式数据简单实践
如果你也跟我一样对标准理解困难,也不看那个上面哪些内容。你自己拿Excel软件,自己编辑点数据进去,另存为“.csv”文件。下面就是我制造的测试文件:
这里我构造了几个特殊的例子:
1-1个单元格中文本中有换行,如上图C3列。
2-1个单元格中文本以双引号开始,有1个,有2个,如上图B2、B4。
3-1个单元格中文本不以双引号开始,包含1个,包含3个,如上图A3、A6。
4-1个单元格中文本以逗号开始,包含1个逗号,3个逗号,逗号结尾,如上图A5,B5,C5。
5-1个单元格中文本包含斜杠、反斜杠,如C5、A4。
下面是我构造了几个特殊的例子在文本编辑器中的展示:
1-使用微软的Excel软件,另存为CSV文件,换行符保存为Windows的换行符(CRLF)。但是我在Mac系统输入的C3列的换行符是Unix的换行符(LF)。为此我试了下,在命令行下使用vi编辑的文件默认的换行符也是(LF)。至于为什么不是Mac的换行符(CR),我也没搞懂。
2-双引号如果出现在单元格文本中第一个字符,那么会有2个双引号要把这个双引号包含起来,还得有一个双引号作为转义字符,所以,一个双引号变成了2(边界)+1(转义)+1=4个,两个双引号变成了2(边界)+2(转义)+2=6个。于是B2的2个双引号变成了6个,B4的1个双引号变成了4个。
3-如果单元格文本的第一个字符不是双引号,而在后面的字符中有双引号,则不会有文本界定符也不会有转义,还是原来的样子。
4-如果单元格文本中包含逗号不论在什么位置,单元格所有的文字都会被文本界定符双引号包含起来。
5-不论是斜杠还是反斜杠都不触发文本界定符和转义符“双引号”,CSV文件的转义符号是双引号。
微软帮助文档对CSV格式文件的描述为:“将工作簿另存为以逗号分隔的文本文件,以便在其他 Windows 操作系统上使用,并确保正确解释制表符、换行符和其他字符。 仅保存活动工作表。”
凡是符合以上实践标准的数据格式的CSV格式的文件,是可以被Excel识别的,也是可以被Dataworks识别的。
4-Dataworks对CSV文件的支持
Dataworks支持文本文件类型很多,一般CSV文件导入常见于textfile,或者是FTP上的textfile、OSS上的textfile。如下:
以上来源于:https://github.com/alibaba/DataX
我引用了datax的官方文档来做说明,因为DataWorks离线数据集成文本文件底层使用的是datax。以读取文本文件的组件TxtFileReader来做说明。
TxtFileReader实现了从本地文件读取数据并转为DataX协议的功能,本地文件本身是无结构化数据存储,对于DataX而言,TxtFileReader实现上类比OSSReader,有诸多相似之处。目前TxtFileReader支持功能如下:
l 支持且仅支持读取TXT的文件,且要求TXT中shema为一张二维表。
l 支持类CSV格式文件,自定义分隔符。
l 支持多种类型数据读取(使用String表示),支持列裁剪,支持列常量
l 支持递归读取、支持文件名过滤。
l 支持文本压缩,现有压缩格式为zip、gzip、bzip2。
l 多个File可以支持并发读取。
暂时不能做到:
l 单个File支持多线程并发读取,这里涉及到单个File内部切分算法。
l 单个File在压缩情况下,从技术上无法支持多线程并发读取。
参数说明
l path
描述:本地文件系统的路径信息,注意这里可以支持填写多个路径。
当指定单个本地文件,TxtFileReader暂时只能使用单线程进行数据抽取。
当指定多个本地文件,TxtFileReader支持使用多线程进行数据抽取。线程并发数通过通道数指定。
当指定通配符,TxtFileReader尝试遍历出多个文件信息。例如: 指定/*代表读取/目录下所有的文件,指定/bazhen/*代表读取bazhen目录下游所有的文件。TxtFileReader目前只支持*作为文件通配符。
特别需要注意的是,DataX会将一个作业下同步的所有Text File视作同一张数据表。用户必须自己保证所有的File能够适配同一套schema信息。读取文件用户必须保证为类CSV格式,并且提供给DataX权限可读。
特别需要注意的是,如果Path指定的路径下没有符合匹配的文件抽取,DataX将报错。
必选:是
默认值:无
l column
描述:读取字段列表,type指定源数据的类型,index指定当前列来自于文本第几列(以0开始),value指定当前类型为常量,不从源头文件读取数据,而是根据value值自动生成对应的列。
默认情况下,用户可以全部按照String类型读取数据,配置如下:
"column": ["*"]
用户可以指定Column字段信息,配置如下:
{
"type": "long",
"index": 0 //从本地文件文本第一列获取int字段
},
{
"type": "string",
"value": "alibaba" //从TxtFileReader内部生成alibaba的字符串字段作为当前字段
}
对于用户指定Column信息,type必须填写,index/value必须选择其一。
必选:是
默认值:全部按照string类型读取
l fieldDelimiter
描述:读取的字段分隔符
必选:是
默认值:,
l compress
描述:文本压缩类型,默认不填写意味着没有压缩。支持压缩类型为zip、gzip、bzip2。
必选:否
默认值:没有压缩
l encoding
描述:读取文件的编码配置。
必选:否
默认值:utf-8
l skipHeader
描述:类CSV格式文件可能存在表头为标题情况,需要跳过。默认不跳过。
必选:否
默认值:false
l nullFormat
描述:文本文件中无法使用标准字符串定义null(空指针),DataX提供nullFormat定义哪些字符串可以表示为null。
例如如果用户配置: nullFormat:"\N",那么如果源头数据是"\N",DataX视作null字段。
必选:否
默认值:\N
l csvReaderConfig
描述:读取CSV类型文件参数配置,Map类型。读取CSV类型文件使用的CsvReader进行读取,会有很多配置,不配置则使用默认值。
必选:否
默认值:无
常见配置:
"csvReaderConfig":{
"safetySwitch": false,
"skipEmptyRecords": false,
"useTextQualifier": false
}
所有配置项及默认值,配置时 csvReaderConfig 的map中请严格按照以下字段名字进行配置:
boolean caseSensitive = true;
char textQualifier = 34;
boolean trimWhitespace = true;
boolean useTextQualifier = true;//是否使用csv转义字符
char delimiter = 44;//分隔符
char recordDelimiter = 0;
char comment = 35;
boolean useComments = false;
int escapeMode = 1;
boolean safetySwitch = true;//单列长度是否限制100000字符
boolean skipEmptyRecords = true;//是否跳过空行
boolean captureRawRecord = true;
以上内容来源于:
https://github.com/alibaba/DataX/blob/master/txtfilereader/doc/txtfilereader.md
支持总结
CSV文件作为一个二维表格式的纯文本文件,要导入到数据库中,需要映射成一张二维表。所以,这里的一些参数要对CSV文件的格式进行定义后才能导入。
1-CSV文件中不确定的属性,字符编码、换行符。因为不同操作系统和不同国家地区使用的字符集的不同,导入前需要定义这两个属性。
2-超越CSV的定义,字段分隔符。默认是逗号,但是可以是其他符号,我最常用的还是“|”。
3-导入相关的数据映射属性。是否跳过首行,很多CSV文件首行是字段名(string),导入的时候与目标端数据类型不一致(number)。
4-导入文本相关的CSV的属性,csvReaderConfig属性,例如转义字符。
5-与CSV导入表格相关的属性,需要定义CSV中每一列的数据类型,需要确定文本是否经过压缩,多个文本导入的路径这些。
整体来看对CSV的支持目前足以满足对数据集成的需求,可以支撑任何CSV数据的导入。所以,这部分功能对CSV的支持是强调且完整的。
5-参考:
1-关于RFC的参考
(1)百度百科RFC
https://baike.baidu.com/item/RFC/1840?fr=ge_ala
Request For Comments(RFC),是一系列以编号排定的文件。文件收集了有关互联网相关信息,以及UNIX和互联网社区的软件文件。RFC文件是由Internet Society(ISOC)赞助发行。基本的互联网通信协议都有在RFC文件内详细说明。RFC文件还额外加入许多在标准内的论题,例如对于互联网新开发的协议及发展中所有的记录。因此几乎所有的互联网标准都有收录在RFC文件之中。
(2)百度百科ISOC
https://baike.baidu.com/item/ISOC/1247005?fromModule=lemma_inlink
国际互联网协会(Internet Society,简称ISOC)正式成立于1992年1月,是一个全球性的互联网组织,在推动互联网全球化,加快网络互连技术、发展应用软件、提高互联网普及率等方面发挥重要的作用。
(3)百度百科MIME
https://baike.baidu.com/item/MIME/2900607?fr=ge_ala
MIME(Multipurpose Internet Mail Extensions)多用途互联网邮件扩展类型。是设定某种扩展名的文件用一种应用程序来打开的方式类型,当该扩展名文件被访问的时候,浏览器会自动使用指定应用程序来打开。多用于指定一些客户端自定义的文件名,以及一些媒体文件打开方式。
(3)RFC文档阅读
RFC 系列文档和 RFC 编辑器的相关说明
https://developer.aliyun.com/article/1174238
如何阅读RFC
https://blog.csdn.net/basil1728/article/details/105338445/
https://blog.csdn.net/alading2009/article/details/84187898
https://www.freebuf.com/column/184598.html
javaCSVFormat.RFC4180文件解析
https://blog.51cto.com/u_16175443/6825450
2-关于CSV的标准
Common Format and MIME Type for Comma-Separated Values (CSV) Files
https://www.rfc-editor.org/rfc/rfc4180
URI Fragment Identifiers for the text/csv Media Type
https://www.rfc-editor.org/rfc/rfc7111
RFC Editor
3-其他
(1)纯文本文档
https://baike.baidu.com/item/%E7%BA%AF%E6%96%87%E6%9C%AC%E6%96%87%E6%A1%A3/5609235?fr=ge_ala
纯文本文档,就是没有任何文本修饰的,没有任何粗体,下划线,斜体,图形,符号或特殊字符及特殊打印格式的文本,只保存文本,不保存其格式设置。将所有的分节符、分页符、新行字符转换为段落标记。
(2)CSV文件
https://blog.51cto.com/u_12935/6862687
CSV格式是分隔的数据格式,有字段/列分隔的逗号字符和记录/行分隔换行符。字段包含特殊字符(逗号,换行符,或双引号),必须以双引号括住。行内包含一个项目是空字符串,可以以双引号括住。字段的值包含双引号时,要双写这个双引号(就像把一个双引号当做转义符一样)。CSV文件格式并不需要特定的字符编码,字节顺序,或行终止格式。
(3)Excel支持的文件格式
(4)datax帮助
https://github.com/alibaba/DataX