1. Node.js 导出 CSV 文件
在实际的工作中,文件格式的转换以及数据导入导出是非常常见的需求之一。转换或者导出数据时,我们往往会指定一个格式,如 txt
,csv
,xlsx
,pdf
或者其他自定义格式。其中 csv
格式是比较常见并且也是通用的一种文件形式。在这一章节中,我们将介绍如何在 Node.js 中导出 csv
格式的文件。
1.1 什么是 CSV 文件
csv
的全称为 逗号分隔值(Comma-Separated Values,CSV)。其本质是文本文件,用逗号(英文半角)对数据进行分割。主要是用来存储表格类型的数据,对于关系型数据库非常友好(数据库工具软件可以直接导入导出 csv
格式的文件)。并且由于其为纯文本,体积小,并且对于不同系统间的兼容性也非常好。
如果我们直接使用记事本或者文本编辑器打开的 csv
文件的话,其格式一般分为两种,一种的值是 “裸露” 在外面的,像下面这样。
aaa,bbb,ccc,ddd,eee CRLF(换行符,一般我们是看不见的)
fff,ggg,hhh,iii,jjj CRLF(换行符,最后一行可有可无)
另一种方式是在值的外面会包上一个双引号。这种形式的好处在于,在双引号中我们的数据可以有换行符、逗号或者引号。(对于双引号中如果还有双引号,则需要再使用一个双引号进行转义。)形式是下面这样。
"aaa","bb CRLF bb","ccc""cc"
"ddd","eee","fff"
在 Windows 系统中,Office 的 Excel 可以直接打开 csv
格式的文件。但是需要注意的一点是,大数字(如 18 位纯数字的身份证号)的值,很有可能变成科学计数法或者末尾变成 0 。
1.2 Node.js 导入导出 CSV
从上面我们可以看出 csv
文件的格式并非严格统一,基本只要使用逗号分隔就可以了。因此在解析方式上也就是对分隔符的解析为主,但没有一个严格和固定的规范。
下面我们将使用原生的 Node.js 来对一个 csv
文件进行解析,让大家对文件的解析有一个大致的认识。首先我们先准备需要解析的 csv
文件,其内容如下(该文件是通过 Navicat 导出的,格式比较标准)。
"char_id","char_name","role","create_time","update_time"
"1","系统管理员","50","2017/8/28 22:58:37","2017/8/28 22:58:37"
"2","系统工程师","20","2017/8/28 22:58:37","2017/8/28 22:58:37"
"3","开发工程师","30","2017/8/28 22:58:37","2017/8/28 22:58:37"
"4","部门主管","40","2017/8/28 22:58:37","2017/8/28 22:58:37"
既然材料都已经备齐了,那么下面我们就使用 Node.js 来进行导入和导出的操作吧。动手之前我们先来梳理一下整个流程。
通过上面的整理,可以知道我们需要做两件事情。
- csv => json
- json => csv
理清楚思路后,我们就正式开始吧。对 Node.js 如果还不熟悉的小伙伴,可以先学习一下 Node.js 的基础再来会更容易理解哦~我们创建一个 csv-convert.js
的文件,在其中编写我们的相关逻辑。
第一步我们先从 csv => json 这一步来做。对 csv 文件的处理,本质是对字符串的处理(从文件中读取的内容为字符串),所以我们再来整理一下 csv 文件的基本特点。
- 第一行为表头
- 最后一行可能为换行符
- 数据以半角逗号分隔
- 每一行数据的数量一致
针对这些特点,我们可以使用 split
和数组的方法对数据进行加工。具体的代码如下。
function csvToJson (file) {
return new Promise((resolve, reject) => {
fs.readFile(file, 'utf-8', (err, data) => {
if (err) {
reject(err)
}
// data 为我们所读取的文件内容,按照换行符进行分割
var dataList = data.split('\r\n')
// 数组的第一位一定是表头,因此我们单独取出第一行,并且用 ',' 分割
var titleList = dataList.shift(0).split(',')
// 如果源文件最后有换行符,则数组的最后一项为空。当为空时,我们舍去最后一行
if (!dataList[dataList.length - 1]) {
dataList.pop()
}
// 剩下为内容的数组
var contentList = dataList
// 使用 map 方法,对行内容与表头进行配对编辑,最终返回一个 JSON 的数组
var jsonList = contentList.map((content) => {
// 对内容同样用 ',' 分割
var tmpList = content.split(',')
var dataObj = {}
tmpList.forEach((_data, index) => {
dataObj[titleList[index]] = _data
})
return dataObj
})
console.log(jsonList)
resolve(jsonList)
})
})
}