【问题标题】:Transform huge CSV files around 2 GB转换大约 2 GB 的巨大 CSV 文件
【发布时间】:2020-11-06 14:32:47
【问题描述】:

我想转换巨大的 CSV 文件并且转换只包括

  1. 删除特定列。
  2. 重命名特定列。

我已经在节点中实现了一个脚本,请在下面找到相同的内容。

  for(const m of metadata) {
    try {
      tempm = m;
      const pipelineAsync = promisify(pipeline);
      if(m.path) {
        let dir = `tmp/exports/${exportId}/processed/${m.type}`;
        let fname = `${dir}/${m.sname}`;
        fs.mkdirSync(dir,{recursive: true}, (err) => {
          if(err) throw err;
        });
        await pipelineAsync(
          fs.createReadStream(m.path),
          csv.parse({delimiter: '\t', columns: true}),
          csv.transform((input) => {
            return Object.assign({}, input);
          }),
          csv.stringify({eol: true, record_delimiter: '\r\n', header: true, delimiter: '\t'}),
          fs.createWriteStream(fname, {encoding: 'utf16le'})
        )
      }
    } catch(e) {
      tempm['transformed'] = false;
      console.log(`error with ${m.path}`)
    } finally {
      tArr.push(tempm);
    }
  }

这在大多数情况下都有效,但对于巨大的 CSV 文件,并非所有数据都写入目标文件。如果源文件包含 1.2GB 的数据,那么我看到目标文件仅包含约 800 MB 的数据。因为,我在循环中处理文件,所以我还看到在同一执行流程中,另一个文件依次包含 80MB 数据,但目标文件仅包含 35MB 数据。

此外,问题是间歇性发生的。

既然我只想操作 csv 列,有没有更有效的方法来执行此操作而不是读取整个文件。

我还了解到 python/perl 能够处理/处理大型 csv 文件,也许我可以将处理部分作为单独的服务进行,然后从我的 node.js 应用程序中调用它。

另外,任何人都可以建议我如何解决并非所有数据都写入目标文件并且管道在两者之间完成的问题。

任何有关如何解决此问题的帮助都会非常有帮助。谢谢。

【问题讨论】:

  • 一些可能对您有帮助的想法:unix.stackexchange.com/questions/317366/…
  • 好吧,你确定要等到文件刷新到磁盘吗?
  • @Tarik 感谢您的回复,我该如何识别?我认为承诺管道将确保这一点。
  • 嗯,是的,这在 Perl (Text::CSV) 和 Python (csv) 中很容易,无论文件有多大,因为 CSV 是面向行的,因此通常由一次读一行。链接的库易于使用且文档齐全,此处有大量示例。

标签: javascript python node.js csv perl


【解决方案1】:

如果你有这么大的文件,你应该使用streams来处理它们。

Node fs API 允许您这样做。

CSV 文件很容易使用流处理。

【讨论】:

  • 是的,但是如果我理解您的代码,您的操作就没有正确。尝试读取文件直到遇到EOL 然后处理单独的行并立即将其推送到写入流。应该这样做。
  • 感谢您的回复,能否请您发布示例代码或建议我可以在哪里修改我的上述代码?
  • 首先:停止使用 csv 解析器,它正在消耗整个文件。尝试找到一个正在处理流的。这个看起来不错:npmjs.com/package/csv-parser
  • 不确定我是否理解正确,在我发布的代码中,我看到一次返回 1 行到 csv.transform,你是想说,csv 解析器将整个文件加载到内存中并且一次读取一行?
  • 我不确定,我无法运行您的代码。我只是假设。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-04
  • 1970-01-01
相关资源
最近更新 更多