Node.js-如何将函数应用于两个流的每个行组合?

时间:2018-10-07 16:54:12

标签: node.js

我正在流传输两个无法容纳在内存中的大文件,我需要逐行比较这两个文件,并应用需要积累一些信息的比较功能。

假设我有两个流:const stream1, stream2。而我需要积累一些结果。举个例子,假设这是两个文件中let count中相同位置的行数的计数。

这是我尝试的方法:

const stream1 = getLineByLineReadable1Somehow(), stream2 = getLineByLineReadable2Somehow();

let count = 0;

stream1.on('readable', () => {
    stream2.on('readble', () => {
        let line1, line2;
        while (line1 = stream1.read()) {
            line2 = stream2.read();
            if (line1 !== line2) count++;
        }
    });
});

console.log(count);

只要两个文件很小,此方法就可以正常工作,但是当文件变大时,它们会完全崩溃。最后提供的计数不正确。不确定发生了什么,但我认为这与两个流之一被多次触发的readable事件有关。在某些时候,两个流之一只是吐出一堆null一会儿。

在此问题上的帮助将不胜感激。谢谢!

1 个答案:

答案 0 :(得分:0)

问题在于,在大文件上,新行到达的事件可能非常不规则。因此,必须有一个中间缓冲区。这是一个有效的代码段:

var readline = require('readline');
var fs = require('fs');

var rs1 = fs.createReadStream('1.log');
var r1 = readline.createInterface({
    input: rs1
});

var rs2 = fs.createReadStream('2.log');
var r2 = readline.createInterface({
    input: rs2
});

var stats = {
    count: [0, 0],
    common: 0,
    closed: 0,
    lines: [
        [],
        []
    ]
}

function compare(line, i) {
    stats.count[i]++;
    if (stats.closed === 0 || stats.lines[1 - i].length > 0) stats.lines[i].push(line);
    while (stats.lines[0].length > 0 && stats.lines[1].length > 0) {
        var L1 = stats.lines[0].shift();
        var L2 = stats.lines[1].shift();
        if (L1 === L2) stats.common++;
    }
}

function close() {
    if (++stats.closed === 2) console.log(stats.count, stats.common, stats.lines[0].length, stats.lines[1].length);
}

r1.on('line', (line) => compare(line, 0))
r2.on('line', (line) => compare(line, 1))

r1.on('close', close);
r2.on('close', close);