使用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中加入列的名字。

这个代码产生的文件内容如下:

writing csv to a file in nodejs

总结

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

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *