Large CSV to JSON/Object in Node.js
Large CSV to JSON/Object in Node.js
我正在尝试做一些看起来不仅应该相当容易完成的事情,而且应该是一个足够常见的任务,可以使用直接的软件包来完成它。我希望获取一个大型CSV文件(从关系数据库表导出)并将其转换为JavaScript对象数组。此外,我想将其导出到.json
文件fixture。
CSV例子:
a,b,c,d
1,2,3,4
5,6,7,8
...
的JSON:
[
{"a": 1,"b": 2,"c": 3,"d": 4},
{"a": 5,"b": 6,"c": 7,"d": 8},
...
]
我已经尝试了几个节点CSV解析器,streamer,自称CSV到json库,但我似乎无法得到我想要的结果,或者如果我可以,它只能在文件较小的情况下工作。我的文件大小接近1 GB,有大约40m行(这将创建40m个对象)。我希望它需要流式输入和/或输出以避免内存问题。
以下是我尝试过的软件包:
- https://github.com/klaemo/csv-stream
- https://github.com/koles/ya-csv
- https://github.com/davidgtonge/stream-convert(工作,但它是这样非常慢,因为我经常更改数据集。解析一个60 MB的csv文件花了将近3个小时)
- https://github.com/cgiffard/CSVtoJSON.js
- https://github.com/wdavidw/node-csv-parser(似乎不是设计用于将csv转换为其他格式)
- https://github.com/voodootikigod/node-csv
我正在使用Node 0.10.6,希望得到关于如何轻松完成此操作的建议。滚动我自己的可能是最好的,但我不确定从哪里开始所有的Node的流特性,特别是因为他们在0.10.x更改了API。
检查node.js csvtojson模块,该模块可以用作库,命令行工具或web服务器插件。https://www.npmjs.org/package/csvtojson。源代码可在以下网址找到:https://github.com/Keyang/node-csvtojson
或从NPM repo安装:
npm install -g csvtojson
支持任何大小的csv数据/字段类型/嵌套json等。一堆功能。
例子var Converter=require("csvtojson").core.Converter;
var csvConverter=new Converter({constructResult:false, toArrayString:true}); // The constructResult parameter=false will turn off final result construction in memory for stream feature. toArrayString will stream out a normal JSON array object.
var readStream=require("fs").createReadStream("inputData.csv");
var writeStream=require("fs").createWriteStream("outpuData.json");
readStream.pipe(csvConverter).pipe(writeStream);
您也可以使用它作为cli工具:
csvtojson myCSVFile.csv
虽然这远远不是一个完整的答案,但您可以基于https://github.com/dominictarr/event-stream找到您的解决方案。改编自自述文件中的示例:
var es = require('event-stream')
es.pipeline( //connect streams together with `pipe`
process.openStdin(), //open stdin
es.split(), //split stream to break on newlines
es.map(function (data, callback) { //turn this async function into a stream
callback(null
, JSON.stringify(parseCSVLine(data))) // deal with one line of CSV data
}),
process.stdout
)
之后,我希望每行都有一堆字符串化的JSON对象。然后需要将其转换为数组,您可以将,
附加到每行的末尾,在最后一行删除它,然后将[
和]
添加到文件的开头和结尾。
parseCSVLine
功能,将CSV值分配给正确的对象属性。这可以在传递文件的第一行之后相当容易地完成。
我注意到库没有在0.10上测试过(至少没有在Travis上测试过),所以要小心。也许你可以自己在源代码上运行npm test
。
我发现了一些更简单的方法来读取csv数据使用csvtojson
代码如下:
var Converter = require("csvtojson").Converter;
var converter = new Converter({});
converter.fromFile("sample.csv",function(err,result){
var csvData = JSON.stringify
([
{resultdata : result[0]},
{resultdata : result[1]},
{resultdata : result[2]},
{resultdata : result[3]},
{resultdata : result[4]}
]);
csvData = JSON.parse(csvData);
console.log(csvData);
});
或者你可以很容易地这样做:
var Converter = require("csvtojson").Converter;
var converter = new Converter({});
converter.fromFile("sample.csv",function(err,result){
console.log(result);
});
下面是第一个代码的结果:
[ { resultdata:
{ 'Header 1': 'A_1',
'Header 2': 'B_1',
'Header 3': 'C_1',
'Header 4': 'D_1',
'Header 5': 'E_1' } },
{ resultdata:
{ 'Header 1': 'A_2',
'Header 2': 'B_2',
'Header 3': 'C_2',
'Header 4': 'D_2',
'Header 5': 'E_2' } },
{ resultdata:
{ 'Header 1': 'A_3',
'Header 2': 'B_3',
'Header 3': 'C_3',
'Header 4': 'D_3',
'Header 5': 'E_3' } },
{ resultdata:
{ 'Header 1': 'A_4',
'Header 2': 'B_4',
'Header 3': 'C_4',
'Header 4': 'D_4',
'Header 5': 'E_4' } },
{ resultdata:
{ 'Header 1': 'A_5',
'Header 2': 'B_5',
'Header 3': 'C_5',
'Header 4': 'D_5',
'Header 5': 'E_5' } } ]
这段代码的源代码在:https://www.npmjs.com/package/csvtojson安装
我希望你有一些想法
你可以使用流来处理大文件。这是你需要做的。这应该可以正常工作。
npm i --save csv2json fs-extra // install the modules
const csv2json = require('csv2json');
const fs = require('fs-extra');
const source = fs.createReadStream(__dirname + '/data.csv');
const output = fs.createWriteStream(__dirname + '/result.json');
source
.pipe(csv2json())
.pipe(output );
我建议您自己实现这个逻辑。Node.js其实很擅长这类任务。
下面的解决方案是使用流,因为它们不会占用你的内存。
安装依赖关系npm install through2 split2 --save
代码import through2 from 'through2'
import split2 from 'split2'
fs.createReadStream('<yourFilePath>')
// Read line by line
.pipe(split2())
// Parse CSV line
.pipe(parseCSV())
// Process your Records
.pipe(processRecord())
const parseCSV = () => {
let templateKeys = []
let parseHeadline = true
return through2.obj((data, enc, cb) => {
if (parseHeadline) {
templateKeys = data
.toString()
.split(';')
parseHeadline = false
return cb(null, null)
}
const entries = data
.toString()
.split(';')
const obj = {}
templateKeys.forEach((el, index) => {
obj[el] = entries[index]
})
return cb(null, obj)
})
}
const processRecord = () => {
return through2.obj(function (data, enc, cb) {
// Implement your own processing
// logic here e.g.:
MyDB
.insert(data)
.then(() => cb())
.catch(cb)
})
}
有关此主题的更多信息,请访问Stefan baumgartner关于此主题的优秀教程。
嗯…很多解决方案,我将添加一个scramjet
:
$ npm install --save scramjet
和
process.stdin.pipe(
new (require("scramjet").StringStream)("utf-8")
)
.CSVParse()
.toJSONArray()
.pipe(process.stdout)
- Using closures in node js
- JS vs JSON for config in Node js
- Class methods in node.js
- Q.all on NodeList in Node
- Azure DocumentDB Stored Procedure in Node.js excute existing
- Bower dependency tilde in Node
- app.get and app.post get value in node.js
- process.exec() in node.js
- Conditional app.use in node - express
- requiring RX.js in node.js
- Strange TypeError in Node.js
- Journey JSON in node.js
- setTimeOut() and setInterval() in Node
- SPDY in Node.js https.request()
- socket.setTimeout() in node.js
- ASYNC in Node.JS
- MVC / websockets in node.js
- Large CSV to JSON/Object in Node.js
- using .pipe() in node
- `stream.Transform.unshift()` in Node.js