高效地在节点中逐行读取文件

我已经知道readline可以用来逐行读取文件,例如

readline .createInterface({input: fs.createReadStream('xxx')}) .on('line', (line) => { apply_regexp_on_line }) .on('close', () => { report_all_regexps }); 

但是,这样做相当慢,因为我比较了grep和JavaScript正则expression式的性能,后者在我testing的正则expression式上有更好的性能。 (见基准 )所以我认为我必须责怪节点asynchronousreadline。

在我的情况下,我不关心asynchronous,我只需要利用JavaScript的快速正则expression式来处理非常大的日志文件(通常是1-2GB,有时甚至达到10GB)。 这样做的最好方法是什么? 我唯一关心的是速度。

奖励积分:一些日志文件是gzipped,所以我需要解压缩它们。 如果有人可以推荐我一个快速的逐行阅读器为纯文本和gzip文本存在,我将非常感激。

这如何抵制你的数据?

 // module linegrep.js 'use strict'; var through2 = require('through2'); var StringDecoder = require('string_decoder').StringDecoder function grep(regex) { var decoder = new StringDecoder('utf8'), last = "", lineEnd = /\r?\n/; var stream = through2({}, function transform(chunk, enc, cb) { var lines = decoder.write(last + chunk).split(lineEnd), i; last = lines.pop(); for (i = 0; i < lines.length; i++) { if (regex.test(lines[i])) this.push(lines[i]); } cb(); }, function flush(cb) { if (regex.test(last)) this.push(last); cb(); }); stream._readableState.objectMode = true; return stream; } module.exports = grep; 

 // index.js 'use strict'; var fs = require('fs'); var zlib = require('zlib'); var grep = require('./linegrep'); function grepFile(filename, regex) { var rstream = fs.createReadStream(filename, {highWaterMark: 172 * 1024}); if (/\.gz$/.test(filename)) rstream = rstream.pipe(zlib.createGunzip()); return rstream .pipe(grep(regex)); } // ------------------------------------------------------------------------- var t = Date.now(), mc = 0; grepFile('input.txt', /boot\.([az]+)_head\./).on('data', function (line) { mc++; console.log(line); }).on('end', function () { console.log( mc + " matches, " + (Date.now() - t) + " ms" ); }); 

这将文件stream转换为线的对象stream,通过您的正则expression式映射它们,并只返回匹配的线。