【问题标题】:How to write a JSON array to a file with Node.js writeStream?如何使用 Node.js writeStream 将 JSON 数组写入文件?
【发布时间】:2018-07-04 16:42:30
【问题描述】:

我编写了一个小 Node.js 脚本来从网站上抓取数据,我在该网站上迭代页面以提取结构化数据。

我为每个页面提取的数据是对象数组的一种形式。

我想我可以使用fs.createWriteStream() 方法创建一个可写流,我可以在每次提取页面后在该流上增量写入数据。

显然,您只能将 String 或 Buffer 写入流,所以我正在做这样的事情:

output.write(JSON.stringify(operations, null, 2));

但最后,一旦我关闭流,JSON 格式错误,因为显然我只是一个接一个地附加每个页面的每个数组,结果如下所示:

[
    { ... },  /* data for page 1 */
    { ... }
][ /* => here is the problem */
    { ... },  /* data for page 2 */
    { ... }
]

我如何才能继续将数组实际附加到输出中而不是链接它们?它甚至可以做到吗?

【问题讨论】:

  • 在处理完所有页面后,您是否有理由不一口气写完所有内容?其他任何东西似乎都有点hacky。
  • 这是因为整个数组最终相当大,所以将其保存在内存中可能最终会影响性能我猜(不确定,这只是我学习流如何工作的一个宠物项目)
  • 问题是没有办法拥有部分(有效的)json数据。这并不是真正可以以任何有意义的方式流式传输的东西。如果数组太大以至于可能影响性能,那么最终生成的 json 文件将太大而无法有效消耗。
  • 如果确实需要逐级输出,那么就单独输出每个“操作”对象,并根据需要写出方括号和逗号即可。
  • 好吧,到目前为止,我有几种可能性可以尝试:1)在进程结束时完全写入文件,2)在写入流时手动将 JSON 构建为字符串(如你建议)和3)作为最后的手段,每页写一个文件。感谢您的帮助,我将深入研究这些解决方案并找出哪个最有效;)

标签: javascript json node.js fs node-streams


【解决方案1】:

你的选择是……

  1. 在内存中保留完整的数组,在处理完所有页面后,只在最后写入 json 文件。
  2. 单独编写每个对象,并手动处理方括号和逗号。

这样的……

//start processing
output.write('[');
//loop through your pages, however you're doing that
while (more_data_to_read()) {
    //create "operation" object
    var operation = get_operation_object();
    output.write(JSON.stringify(operation, null, 2));
    if (!is_last_page()) {
        //write out comma to separate operation objects within array
        output.write(',');
    }
}
//all done, close the json array
output.write(']');

这将创建格式良好的 json。

就个人而言,我会选择#1,因为这似乎是更“正确”的方式。如果您担心数组占用过多内存,那么 json 可能不是数据文件的最佳选择。它不是特别适合非常大的数据集。

在上面的代码示例中,如果进程在中途被中断,那么您将拥有一个无效的 json 文件,因此逐步编写实际上不会使应用程序更具容错性。

【讨论】:

  • 谢谢,我最终在处理结束时编写了文件(选项 1),这确实是最安全的做法。它现在似乎表现不错,所以这里的教训是不要过早地过度优化:)
  • 如果数组大小很大,第一种方法不起作用。就我而言,它拥有超过 150 万个对象。 JSON.stringify 抛出 JAVASCRIPT 头内存不足的错误。
猜你喜欢
  • 2023-03-15
  • 1970-01-01
  • 2018-07-02
  • 1970-01-01
  • 2015-08-25
  • 2017-11-28
  • 2017-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多