使用node-csv来读写CSV文件
前言
我们经常遇到一个很常见的问题,就是从一个csv文件中读取数据。我们可以使用fs模块来得到文件的内容。在这之后,使用特定的库来做解析和进一步分析csv则会简单和方便得多。
现在有很多模块都提供了这个功能,比如neat-csv或者csv-parser。而本文要介绍的是node-csv这一个模块,让我们来看看它是如何使用的。
安装node-csv
这个模块是由csv-generate, csv-parse,csv-transform以及csv-stringify这几个包组成的。你可以按需安装,也可以把他们都一次性安装了。
首先我们来用默认设置来创建一个Node的项目:
npm init -y
下面我们来安装整个node-csv:
npm install node-csv
下面是csv文件的内容,你可以拷贝到一个csv文件中,我们用这个文件来做测试:
Account Name,Account Code,Type,Description Cash,101,Assets,Checking account balance Wages Payable,220,Liabilities,Amount owed to employes for hours not yet paid Rent expense,560,Expenses,Cost of occupied rented facilities during accounting period
使用csv-parse来读取CSV文件
我们可以使用node-csv中的csv-parse来读取csv文件。Csv-parse包提供了很多种方法来解析csv文件–你可以使用callbask,也可以使用stream+callback或者sync的API,当然也支持async的api。本文就使用stream+callback api以及同步的sync api。
Stream+Callback API
我们先来创建一个文件index.js,并且创建parser:
var fs = require('fs');
var parse = require('csv-parse');
var parser = parse({columns: true}, function (err, records) {
console.log(records);
});
fs.createReadStream(__dirname+'/chart-of-accounts.csv').pipe(parser);
这里,我们使用了fs和csv-parse模块,然后创建parser,这里第二个参数就是callback函数,我们可以在这个callback中访问records,或者就像例子中一样先把record打印出来。
这里我们使用的参数不是强制的,你可以使用下面这些参数:
- Delimiter: 默认是逗号,假如你的文件中使用的是别的分隔符,比如分号;,或者管道|你可以设置相关的选项。
- cast:这个选项的默认值是false,这个是用来表示是否把字符串转换成本机的数据类型。比如,一个列的日期域可以转换成Date。
- columns:这个选项是用来表示你是否使用object格式来产生record。默认值是false,也就是records是通过parser用arrays来产生的。假如设为true,parser就是从第一行的column来推测。
最后就是用fs打开文件,然后把它传入到parser中。下面我们来运行试试看:
node index.js
结果如下所示:
[
{
'Account Name': 'Cash',
'Account Code': '101',
Type: 'Assets',
Description: 'Checking account balance'
},
{
'Account Name': 'Wages Payable',
'Account Code': '220',
Type: 'Liabilities',
Description: 'Amount owed to employes for hours not yet paid'
},
{
'Account Name': 'Rent expense',
'Account Code': '560',
Type: 'Expenses',
Description: 'Cost of occupied rented facilities during accounting period'
}
]
有了这个结果,你就可以对这些内容来进行各种处理了。
使用同步API
下面我们来使用同步API来实现:
var fs = require('fs').promises;
var parse = require('csv-parse/lib/sync');
(async function () {
const fileContent = await fs.readFile(__dirname+'/chart-of-accounts.csv');
const records = parse(fileContent, {columns: true});
console.log(records)
})();
这里,我们和之前类似,也还是使用fs模块和csv-parse.这里我们创建了一个async的函数,在它里面我们使用readFile函数来读取内容个,然后使用await等待。
然后使用parser,第一个参数是文件的内容,第二个是一个object参数(这里我们把column设为true)。然后把它赋值给record,然后我们可以使用这个record。
[
{
'Account Name': 'Cash',
'Account Code': '101',
Type: 'Assets',
Description: 'Checking account balance'
},
{
'Account Name': 'Wages Payable',
'Account Code': '220',
Type: 'Liabilities',
Description: 'Amount owed to employes for hours not yet paid'
},
{
'Account Name': 'Rent expense',
'Account Code': '560',
Type: 'Expenses',
Description: 'Cost of occupied rented facilities during accounting period'
}
]
使用csv Stringify来写csv文件
下面我们来看看如何把数据写到csv格式的文件中。这里,我们使用csv-stringify包。我们假设你已经得到一些JSON格式的数据,然后想把它写入到csv文件中。
var someData = [
{
"Country": "Nigeria",
"Population": "200m",
"Continent": "Africa",
"Official Language(s)": "English"
},
{
"Country": "India",
"Population": "1b",
"Continent": "Asia",
"Official Language(s)": "Hindi, English"
},
{
"Country": "United States of America",
"Population": "328m",
"Continent": "North America",
"Official Language": "English"
},
{
"Country": "United Kingdom",
"Population": "66m",
"Continent": "Europe",
"Official Language": "English"
},
{
"Country": "Brazil",
"Population": "209m",
"Continent": "South America",
"Official Language": "Portugese"
}
]
Csv-stringify包也有一些API的选项,Callback API有很多简单的方式来把数据变成string。让我们来看看如何把上面的JSON数据变成string,然后写到文件中:
var fs = require('fs');
var stringify = require('csv-stringify');
stringify(someData, {
header: true
}, function (err, output) {
fs.writeFile(__dirname+'/someData.csv', output);
})
这里我们使用fs和csv-stringify模块,然后使用stringify函数,把数据变成string。我们也传入了一个包含header选项的object。最后,有一个callback函数用来把内容写到文件里。
别的类似cast,columns以及你delimiter也可以加入到选项中。我们例子中使用的是header选项为true来告诉stringifier在第一个record中加入列的名字。
这个代码产生的文件内容如下:

总结
node-csv是一个很小的模块来进行读写,转换csv数据的。我们使用了scv-parse模块来读取csv文件然后使用csv-stringify模块来转换成字符并写到文件中。

Recent Comments