[英]Efficiently read file line-by-line in node
我已经知道readline可以用来逐行读取文件,例如
readline
.createInterface({input: fs.createReadStream('xxx')})
.on('line', (line) => { apply_regexp_on_line })
.on('close', () => { report_all_regexps });
但是,这很慢,因为我比较了grep
和JavaScript regexp的性能,而后者在我测试的regexp上有更好的性能。 (见基准 )所以我认为我必须责怪节点异步readline。
在我的情况下,我根本不关心异步,我只需要利用JavaScript中的快速正则表达式来处理非常大的日志文件(通常为1-2GB,有时高达10GB)。 这样做的最佳方式是什么? 我唯一关心的是速度。
加分:一些日志文件是gzip压缩的,所以我需要解压缩它们。 如果有人可以推荐我一个快速的逐行阅读器,因为存在纯文本和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\.([a-z]+)_head\./).on('data', function (line) {
mc++;
console.log(line);
}).on('end', function () {
console.log( mc + " matches, " + (Date.now() - t) + " ms" );
});
这会将文件流转换为行的对象流,通过正则表达式映射它们并仅返回匹配的行。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.