我正在尝试在node.js中将非常大的json转换为csv,但它花费了太多时间,并且在转换时导致100%的cpu占用。
jsonToCsv: function (data) {
var keys = Object.keys(data[0]);
var csv = [keys.join(",")];
console.time("CSVGeneration");
data.forEach(function (row) {
var line = '';
keys.forEach(function (key) {
if (typeof row[key] === 'string') {
row[key] = "" + file_utils.escapeCsv(row[key]) + "";
}
line += row[key] + ",";
});
csv.push(line);
});
console.timeEnd("CSVGeneration");
csv = csv.join("\n");
return csv;
},
escapeCsv: function (x) {
if (x)
return ('' + x.replace(/"/g, '').replace(/,/g, ' ').replace(/\n/g, " ").replace(/\r/g, " ") + '');
else
return ('');
},
在 1Lac 行的平均运行中,它从未恢复到均匀的日志时间。我必须手动终止该进程。
有人可以提出更好的替代方案吗?
最佳答案
在回答这个问题之前:假设您的代码正常工作,这个问题属于 https://codereview.stackexchange.com/ .
至于你的问题:
- 像
forEach()
这样的新数组访问函数虽然在编码时相当舒适,但通常性能不太好。在性能关键情况下,简单的for
循环是更好的选择。 - 在
escapeCsv()
中,您应用 4 种不同的正则表达式替换,每种替换仅针对一个字符。将它们合二为一。 - 假设您的数据已经以允许 Csv 转换的方式构建(
data
是一个对象数组,每个对象都具有相同的属性),则无需单独检索 key 每个对象。
应用它,产生以下代码:
function escapeCsv(x) {
if (x) {
return ('' + x).replace( /[",\n\r]/gi, '' );
} else {
return ('');
}
}
function jsonToCsv(data) {
var keys = Object.keys(data[0]),
csv = [keys.join(",")];
var row = new Array( keys.length );
for (var i = 0; i < data.length; i++) {
for (var j = 0; j < keys.length; j++) {
if (typeof data[i][keys[j]] === 'string') {
row[j] = '"' + escapeCsv(data[i][keys[j]]) + '"';
} else {
row[j] = data[i][keys[j]] || '';
}
}
csv.push(row.join(','));
}
return csv.join("\n");
}
根据 jsPerf 的说法,仅此一项就可以将性能提高约 3-5 倍。
如果您生成的 CSV 可以直接流式传输到文件或客户端,则可以进一步改进并减少内存负载,因为 CSV 不必存储在内存中。
Fiddle to play around with the functions原始名称与您的名称相同,新名称带有后缀 2
。
关于Node.js 中的 Json 到 csv,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27481929/