Подтвердить что ты не робот

Эффективно читайте файл по строкам в node

Я уже узнал, что readline можно использовать для чтения файла по строкам, например.

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

Однако это довольно медленно, поскольку я сравнивал производительность grep и JavaScript regexp, а последний имеет лучшую производительность в тестируемых регулярных выражениях. (см. benchmark). Поэтому я считаю, что я должен обвинять асинхронную readline node.

В моей ситуации мне вообще неинтересно, я просто должен использовать быстрое регулярное выражение JavaScript для обработки очень больших файлов журналов (обычно 1-2 ГБ, иногда до 10 ГБ). Каков наилучший способ сделать это? Меня беспокоит только скорость.

Бонусные баллы: некоторые из файлов журнала gzipped, поэтому мне нужно их распаковать. Если кто-то может порекомендовать мне быстрый линейный считыватель для обычного текста и gzipped-текста, я был бы очень благодарен.

4b9b3361

Ответ 1

Как это задерживается против ваших данных?

// 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" );
});

Это превращает поток файлов в поток объектов строк, отображает их через ваше регулярное выражение и возвращает только соответствующие строки.