我试图读取一个大文件一行在一次。我在Quora上找到了一个关于这个主题的问题,但我错过了一些联系,把整个事情联系在一起。
var Lazy=require("lazy");
new Lazy(process.stdin)
.lines
.forEach(
function(line) {
console.log(line.toString());
}
);
process.stdin.resume();
我想要弄清楚的是如何一次从文件中读取一行,而不是像本例中那样读取STDIN。
我试着:
fs.open('./VeryBigFile.csv', 'r', '0666', Process);
function Process(err, fd) {
if (err) throw err;
// DO lazy read
}
但这并不奏效。我知道在必要时我可以使用PHP之类的东西,但我想弄清楚这个问题。
我不认为其他答案会起作用,因为文件比我运行它的服务器的内存大得多。
当我试图处理这些行并将它们写入另一个流时,我最终使用Lazy逐行读取大量内存泄漏,这是由于节点工作中的drain/pause/resume方式(参见:http://elegantcode.com/2011/04/06/taking-baby-steps-with-node-js-pumping-data-between-streams/(我喜欢这个家伙顺便说一句))。我还没有仔细研究Lazy,无法确切地理解其中的原因,但是我无法暂停读流以允许在Lazy退出的情况下进行排泄。
我写了代码来处理大量的csv文件到xml文档,你可以在这里看到代码:https://github.com/j03m/node-csv2xml
如果你用Lazy line运行之前的版本,它就会泄露。最新的版本完全没有泄露,你可以把它作为一个阅读器/处理器的基础。虽然我有一些定制的东西在里面。
编辑:我想我还应该指出,我用Lazy编写的代码工作得很好,直到我发现自己编写了足够大的xml片段,因为必要而耗尽/暂停/恢复。对于较小的块,这是可以的。
有一个很好的模块可以逐行读取文件,它叫做行读取器
用它你只需要写:
var lineReader = require('line-reader');
lineReader.eachLine('file.txt', function(line, last) {
console.log(line);
// do whatever you want with line...
if(last){
// or check if it's the last one
}
});
如果你需要更多的控制,你甚至可以用“java风格”界面迭代文件:
lineReader.open('file.txt', function(reader) {
if (reader.hasNextLine()) {
reader.nextLine(function(line) {
console.log(line);
});
}
});