【问题标题】:Javascript Read large files failedJavascript读取大文件失败
【发布时间】:2017-07-09 09:08:23
【问题描述】:

一个 JSON 文件为 6 GB。使用以下代码阅读时,

var fs = require('fs');
var contents = fs.readFileSync('large_file.txt').toString();

出现以下错误:

buffer.js:182
    throw err;
    ^

RangeError: "size" argument must not be larger than 2147483647
    at Function.Buffer.allocUnsafe (buffer.js:209:3)
    at tryCreateBuffer (fs.js:530:21)
    at Object.fs.readFileSync (fs.js:569:14)
    at Object.<anonymous> (/home/readHugeFile.js:4:19)
    at Module._compile (module.js:569:30)
    at Object.Module._extensions..js (module.js:580:10)
    at Module.load (module.js:503:32)
    at tryModuleLoad (module.js:466:12)
    at Function.Module._load (module.js:458:3)
    at Function.Module.runMain (module.js:605:10)

有人可以帮忙吗?

【问题讨论】:

标签: javascript file io


【解决方案1】:

BufferreadFileSync() 在内部用于保存文件数据)的最大大小约为 2GB(来源:https://nodejs.org/api/buffer.html#buffer_buffer_kmaxlength)。

您可能需要一个流式 JSON 解析器,例如 JSONStream,来处理您的文件:

const JSONStream = require('JSONStream');
const fs         = require('fs');

fs.createReadStream('large_file.json')
  .pipe(JSONStream.parse('*'))
  .on('data', entry => {
    console.log('entry', entry);
  });

【讨论】:

  • 嗨@robertklep,我正在编写一个CLI 应用程序,我需要在其中解析一个大的JSON 文件,并响应用户。您的代码完成了这项工作,但它是异步的。是否有推荐的同步处理流的方法?谢谢
  • @mils 在此示例中流提供的主要功能是能够以增量方式解析文件。就您而言,听起来您想一口气读取/解析文件,这将需要多 GB 的 RAM。你确定那是你想要的吗? AFAIK,没有任何同步流实现(除此之外,流本质上是基于事件的)。
  • 嗨@robertklep,我基本上是对文件进行多次传递。第一遍从 JSON 文件中获取一组唯一的 id,然后对于每个 id,我执行另一遍,检索更深层次的数据。这就是我保持低内存使用的方式。但是我需要在第 1 步完全完成后执行第 2 步(即for(id in ids)),并将结果返回给用户。我想也许我只是一个使用 javascript 的 n00b。是否有解决同步/异步问题的“经典”方法?再次感谢
  • @mils 观察到可读流在读取所有数据后会发出end 事件,这可能会有所帮助。在您的情况下,一旦第 1 步的 end 事件触发,您就可以开始第 2 步。这样,您可以链接流操作。
  • 缓冲区最大 2GB 对于今天的标准来说似乎太小了。有谁知道如何增加这个?为什么它必须这么小?这是 Javascript (v8) 本身的基本限制吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-04-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多