所以我用了fs.readFile()它给了我



由于fs.readFile()在调用回调之前将整个文件加载到内存中,我应该改用fs.createReadStream()吗?

那就是我以前使用readFile做的事情:

fs.readFile('myfile.json', function (err1, data) {
    if (err1) {
        console.error(err1);
    } else {
        var myData = JSON.parse(data);
        //Do some operation on myData here
    }
}

抱歉,我是流媒体新手。以下是做相同事情但使用流媒体的正确方法?
var readStream = fs.createReadStream('myfile.json');

readStream.on('end', function () {
    readStream.close();
    var myData = JSON.parse(readStream);
    //Do some operation on myData here
});

谢谢

最佳答案

如果文件很大,则可以,流式传输将是您要处理的方式。但是,在第二个示例中,您要做的是让流将所有文件数据缓冲到内存中,然后在end上进行处理。这种方式与readFile本质上没有什么不同。

您将要 checkout JSONStream。流式传输的意思是您要处理流过的数据。在您的情况下,您显然必须执行此操作,因为您无法一次将整个文件都缓冲到内存中。考虑到这一点,希望这样的代码有意义:

JSONStream.parse('rows.*.doc')

请注意,它具有一种查询模式。那是因为您将无法同时处理文件中的整个JSON对象/数组,因此您必须就如何让JSONStream在找到数据时处理数据的方式进行更多思考。

您可以使用JSONStream本质上查询您感兴趣的JSON数据。这样您就永远不会将整个文件缓冲到内存中。它的不利之处在于,如果您确实需要所有数据,那么您将不得不多次流传输文件,使用JSONStream当时仅提取您需要的数据,但是在这种情况下,您不需要很多选择。

您还可以使用JSONStream顺序解析数据,并执行类似将其转储到数据库中的操作。
JSONStream.parseJSON.parse相似,但它返回流而不是返回整个对象。当解析流获得足够的数据以形成与您的查询匹配的整个对象时,它将发出data事件,其中数据是与您的查询匹配的文档。一旦配置了数据处理程序,就可以将读取流传输到解析流中,并观察魔术的发生。

例子:
var JSONStream = require('JSONStream');
var readStream = fs.createReadStream('myfile.json');
var parseStream = JSONStream.parse('rows.*.doc');
parseStream.on('data', function (doc) {
  db.insert(doc); // pseudo-code for inserting doc into a pretend database.
});
readStream.pipe(parseStream);

这是帮助您了解正在发生的事情的详细方法。这是一种更简洁的方法:
var JSONStream = require('JSONStream');
fs.createReadStream('myfile.json')
  .pipe(JSONStream.parse('rows.*.doc'))
  .on('data', function (doc) {
    db.insert(doc);
  });

编辑:

为了进一步了解正在发生的事情,请尝试这样思考。假设您有一个巨大的湖泊,并且想要处理水以对其进行净化,然后将水转移到新的水库中。如果您有一架带有巨大水桶的巨型魔法直升机,那么您可以飞越湖面,将湖水放入水桶中,向其中添加处理化学品,然后将其飞到目的地。

当然,问题在于没有这样的直升机可以处理那么多的重量或体积。这根本不可能,但这并不意味着我们无法以其他方式实现目标。因此,您可以在湖泊和新水库之间 build 一系列河流(溪流)。然后,您在这些河流中建立了净化站,以净化流经该净化站的所有水。这些站可以以多种方式运行。也许可以这么快地进行处理,以至于您可以让河流自由流动,而净化只会在水以最大速度顺流而下时发生。

还可能需要花费一些时间来处理水,或者工作站需要一定量的水才能有效处理水。因此,您将河流设计成有闸门,并控制从湖水到河流的流量,让水位站仅缓冲所需的水,直到他们完成工作并将下游的纯净水释放到最终为止。目的地。

这几乎就是您要对数据进行的处理。解析流是您的清理站,它将缓冲数据,直到它足以形成与您的查询匹配的整个文档为止,然后将数据仅推送到下游(并发出data事件)。

Node 流很不错,因为大多数时候您不必处理打开和关闭门的问题。 Node 流足够聪明,可以在流缓冲一定数量的数据时控制回流。好像清洗站和湖上的闸门正在互相交谈以求出理想的流量。

如果您具有流数据库驱动程序,那么理论上您将能够创建某种插入流,然后执行parseStream.pipe(insertStream)而不是手动处理data事件:D。这是在另一个文件中创建JSON文件的过滤版本的示例。
fs.createReadStream('myfile.json')
  .pipe(JSONStream.parse('rows.*.doc'))
  .pipe(JSONStream.stringify())
  .pipe(fs.createWriteStream('filtered-myfile.json'));

09-10 03:33