Json 到 node.js 中的 csv

Posted

技术标签:

【中文标题】Json 到 node.js 中的 csv【英文标题】:Json to csv in node.js 【发布时间】:2015-02-13 10:10:46 【问题描述】:

我正在尝试在 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 行时,它从未恢复到甚至记录时间。我不得不手动终止该进程。

有人可以提出更好的替代方案吗?

【问题讨论】:

旁注:为什么你的函数接受cb参数,却直接返回结果?此外,您是否检查过是否实际生成了行(例如,forEach() 内的调试输出? 对不起。 cb 是多余的,应该被删除。 是的,行已生成,但占用了太多内存和 cpu。有什么有效的内存解决方案吗? 【参考方案1】:

在回答这个问题之前:假设您的代码正在运行,这个问题属于https://codereview.stackexchange.com/。

至于你的问题:

forEach() 这样的新数组访问函数虽然在编码时相当舒适,但通常性能不佳。一个简单的for 循环是性能关键情况下的更好选择。 在escapeCsv() 中,您应用了4 个不同的正则表达式替换,每个替换为一个字符。将它们合二为一。 假设您的数据已经以某种方式结构化,允许 Csv 转换(data 是一个对象数组,每个对象都具有相同的属性),没有必要为每个对象单独检索键。李>

应用这个,产生以下代码:

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

jsPerf.com comparison

【讨论】:

感谢您的宝贵意见,我还不知道 codereview.stackexchange。我将尝试建议的更改并进行更新。 @Hitesh 有用于生成 CSV 的库顺便说一句:github.com/wdavidw/node-csv 我也一定会尝试的。实际上我面临的问题是,在创建这个 csv 之前,除了内存中的整个数据之外,我还有一个巨大的堆栈调用。在创建 csv 时,整个设置内存不足。现在我正在考虑将这个内存计算一起移动到磁盘上。对此有何建议? @Hitesh 在不了解太多细节的情况下很难提出建议。为了减少内存消耗,您可以使用管道:从一个文件中读取(例如,逐行),处理它并立即写入输出文件。这样,在任何时间点,您的内存中都只有一行数据。但如果该方法可行,则取决于您的数据和计算... 我正在尝试几乎相同的路径,唯一的区别是源作为数据库而不是文件。感谢您的意见。

以上是关于Json 到 node.js 中的 csv的主要内容,如果未能解决你的问题,请参考以下文章

对 Node.js 的 xml 到 json 有啥建议吗?

使用 Node.js 对 JSON 中的字符串大小有限制吗?

如何使用 node.js 将 EXCEL 文件数据读取到 json

Node.js 中 JSON 对象中的 JSON 对象 [关闭]

如何在 Node.js 的一个 json 中附加两个查询结果

如何更新json文件中的值并通过node.js保存