假设你拥有一个超过1GB的大型CSV文件,其中包含记录ID:
655453
4930285
493029
4930301
493031
...
对于每个
id
,您想通过REST API调用获取记录数据,本地转换并将其插入到本地数据库中。如何使用Node.js的可读流(Readable Stream
)实现这一点?我的问题基本上是这样的:如何逐行读取一个非常大的文件,对每一行运行异步函数,并且[可选地]能够从特定行开始读取文件?以下是我从Quora问题中学习使用fs.createReadStream
的内容:http://www.quora.com/What-is-the-best-way-to-read-a-file-line-by-line-in-node-js。var fs = require('fs');
var lazy = require('lazy');
var stream = fs.createReadStream(path, {
flags: 'r',
encoding: 'utf-8'
});
new lazy(stream).lines.forEach(function(line) {
var id = line.toString();
// pause stream
stream.pause();
// make async API call...
makeAPICall(id, function() {
// then resume to process next id
stream.resume();
});
});
但是,那个伪代码行不通,因为
lazy
模块 强制你读取整个文件(作为流,但没有暂停)。所以这种方法似乎行不通。另一件事是,我想能够从特定行开始处理此文件。原因是,每个
id
的处理(调用 api、清理数据等)可能需要半秒钟的时间,因此我不想每次都从文件开头开始。我想使用的天真方法是只捕获上次处理的最后一个 id 的行号,并保存它。然后,当你再次解析文件时,逐行遍历所有 id,直到找到你停止的行号,然后进行 makeAPICall
业务。另一种天真的方法是编写小文件(比如 100 个 id),逐个处理每个文件(数据集小得足以在没有 IO 流的情况下全部放在内存中)。有更好的方法吗?我可以看出这会变得棘手(也就是 node-lazy 可以发挥作用的地方),因为
stream.on('data', function(chunk) {});
中的 chunk
可能只包含一行的 部分(如果缓冲区大小很小,每个块可能是 10 行,但由于 id
的可变长度,它可能只有 9.5 行或其他)。这就是我想知道上述问题的最佳方法的原因。