2015-06-28 5 views
9

Während meiner NodeJS-Lernreise fand ich diesen Beispielcode in einem Buch (NodeJS in Practice), das Streams verwendet, um Übereinstimmungen in Daten zu finden, die von einem anderen Stream kommen.Kann dieser Code einige Übereinstimmungen verlieren?

var Writable = require('stream').Writable; 
var util = require('util'); 
module.exports = CountStream; 
util.inherits(CountStream, Writable); 

function CountStream(matchText, options) { 
    Writable.call(this, options); 
    this.count = 0; 
    this.matcher = new RegExp(matchText, 'ig'); 
} 

CountStream.prototype._write = function(chunk, encoding, cb) { 
    var matches = chunk.toString().match(this.matcher); 
    if (matches) { 
     this.count += matches.length; 
    } 
    cb(); 
}; 

CountStream.prototype.end = function() { 
    this.emit('total', this.count); 
}; 

Und der Code, der den Strom verwendet:

var CountStream = require('./countstream'); 
var countStream = new CountStream('book'); 
var http = require('http'); 

http.get('http://www.manning.com', function(res) { 
    res.pipe(countStream); 
}); 

countStream.on('total', function(count) { 
    console.log('Total matches:', count); 
}); 

Ist es nicht möglich, einige Spiele, wenn ein Spiel bricht in zwei Stücke von Daten zu verlieren?

Zum Beispiel der erste Teil der Daten enthalten 'This a bo' und der andere Teil enthält 'ok von mir.' die niemand hat die Buch unabhängig, aber die gesamten Daten enthält eine Buch.

Was wäre die beste Lösung, um alle Übereinstimmungen zu finden?

+0

Gut entdeckt. Ja, ich würde sagen, es kann Spiele verlieren. Wahrscheinlich nicht sehr oft, weil ich denke, dass die Stücke groß sein würden, was den Käfer intermittierend macht - die schlimmste Art von Käfer. – James

+2

In der Tat ist es. Auch wenn die Mustergröße größer als die Chunk-Größe ist (was für die meisten Anwendungsfälle normalerweise kein so großes Problem darstellt). Eine Möglichkeit, dies zu vermeiden - wenn Sie nur Teilstrings finden müssen - wäre [KMP] (https://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm) oder irgendein anderer Algorithmus, der dazu gebracht werden kann, auf einer strombasierten Weise zu arbeiten. @James: Beat mich dazu! Ich bin eine langsame Schreibkraft. Seufzer. – galactocalypse

+0

Brauchen Sie eigentlich Regex, oder suchen Sie einfache Übereinstimmungen? – Bergi

Antwort

1

Also, wie ich in meinen Kommentaren erklären, wenn Sie die maximale Länge der Zeichenfolgen durch Ihre Regex kennen (um die maximale Länge zu berechnen, siehe die sehr gute Antwort bei https://stackoverflow.com/a/31173778/4114922), könnten Sie den vorherigen Chunk zwischenspeichern und verketten zu dem neuen Brocken. Mit dieser Methode, denke ich, wirst du keine Übereinstimmung verlieren.

var Writable = require('stream').Writable; 
var util = require('util'); 
module.exports = CountStream; 
util.inherits(CountStream, Writable); 

function CountStream(matchText, maxPatternLength, options) { 
    Writable.call(this, options); 
    this.count = 0; 
    this.matcher = new RegExp(matchText, 'ig'); 

    this.previousCache = undefined; 
    this.maxPatternLength = maxPatternLength; 
} 

CountStream.prototype._write = function(chunk, encoding, cb) { 
    var text; 
    if(this.previousCache === undefined) { 
     text = chunk.toString(); 
    } 
    else { 
     text = this.previousCache + chunk.toString(); 
    } 
    var matches = text.match(this.matcher); 
    if (matches) { 
     this.count += matches.length; 
    } 

    this.previousCache = text.substring(text.length - this.maxPatternLength); 

    cb(); 
}; 

CountStream.prototype.end = function() { 
    this.emit('total', this.count); 
};