2016-04-02 2 views
3

Nach NodeJS docs(v5.10.0) für ein lesbares stream:Set-Codierung für ein NodeJS Trans Strom in einer sicheren Weise

es besser ist, readable.setEncoding('utf8') zu verwenden, als die Arbeit mit Puffern direkt buf.toString(encoding) verwenden. Dies liegt daran, „Multi-Byte-Zeichen (...) würde sonst möglicherweise verstümmelt werden. Wenn Sie die Daten als Strings lesen mögen, immer diese Methode verwenden.

Meine Frage ist, wie diese umzusetzen Verwendung für die neuen API-Streams zu transformieren. Es gibt jetzt keine Notwendigkeit, durch die Vererbung ausführliche Methode zu gehen.

zum Beispiel so, dies als ein Weg funktionieren würde stdin in einen oberen Fall Zeichenfolge

const transform = require("stream").Transform({ 
    transform: function(chunk, encoding, next) { 
    this.push(chunk.toString().toUpperCase()); 
    next(); 
    } 
}); 

process.stdin.pipe(transform).pipe(process.stdout); 

zu transformieren Dies würde jedoch t erscheinen o gehen Sie gegen die Empfehlung, toString() auf Puffern nicht zu verwenden. Ich habe versucht die Instanz-Transformation modifiziert durch Codierung „UTF-8“, wie diese Einstellung:

const transform = require("stream").Transform({ 
    transform: function(chunk, encoding, next) { 
    this.push(chunk.toUpperCase()); //chunk is a buffer so this doesn't work 
    next(); 
    } 
}); 
transform.setEncoding("utf-8"); 

process.stdin.pipe(transform).pipe(process.stdout); 

Nach Inspektion, transform im ersten Fall hat eine Codierung von null, während in der zweiten es tatsächlich verändert hat zu "UTF-8". Dennoch ist der an die Transformationsfunktion übergebene Chunk immer noch ein Puffer. Ich dachte, dass durch Setzen der Codierung toString() Methode übersprungen werden könnte, aber das ist nicht der Fall.

Ich habe auch versucht, die read Methode wie in den lesbaren und Duplex-Beispielen zu erweitern, aber das ist nicht erlaubt.

Gibt es eine Möglichkeit, toString() loszuwerden?

Antwort

1

Sie haben Recht. Die Verwendung von Buffer#toString direkt in Ihrer _transform-Methode ist schlecht. SetEncoding soll jedoch von lesbaren Datenströmen Consumern verwendet werden (d. H. Dem Code, der aus Ihrem Transformationsdatenstrom liest). Sie sind Implementieren einen Transformations-Stream. Es ändert nicht die Eingabe Ihrer _transform-Methode für Sie.

Intern lesbare Streams verwenden StringDecoder, wenn der Benutzer die automatische Dekodierung aktiviert hat. Sie können es auch in Ihrer Transformationsmethode verwenden.

Hier ist ein code comment zu erklären, wie es funktioniert:

[StringDecoder] decodiert den gegebenen Puffer und gibt ihn als JS String, der garantiert wird keine Teil Multi-Byte-Zeichen enthalten. Jedes partielle Zeichen, das am Ende des Puffers gefunden wird, ist zwischengespeichert und wird zurückgegeben, wenn erneut mit den verbleibenden Bytes geschrieben wird.

So könnte Ihr Beispiel wie folgt umformuliert werden:

var StringDecoder = require('string_decoder').StringDecoder 
const transform = require("stream").Transform({ 
    transform: function(chunk, encoding, next) { 
    if(!this.myStringDecoder) this.myStringDecoder = new StringDecoder('utf8') 
    this.push(this.myStringDecoder.write().toUpperCase()); 
    next(); 
    } 
}); 

process.stdin.pipe(transform).pipe(process.stdout); 
+0

Mein erster Schnipsel funktioniert wie es ist, so gäbe es nicht die Notwendigkeit, direkt StringDecoder zu verwenden. Ich bin nur verwirrt, die Dokumente sagen, dass Transform-Instanzen "sowohl die lesbaren und beschreibbaren Schnittstellen implementieren", wenn für das, was Sie sagen, es nicht der Fall zu sein scheint.StringDecoder macht genau das Gegenteil von dem, was für Readable – cortopy

+0

empfohlen wird. Ihr Snippet funktioniert so lange, wie keine Multibyte-Zeichen in verschiedene Blöcke aufgeteilt sind. Ich empfehle die Verwendung von String-Decodern für die Transformation von Streams, die an Text arbeiten. Die Dokumente sind ein bisschen ambiguos. Sie geben lediglich an: "Rufen Sie diese Funktion auf, um den Stream zu veranlassen, unbearbeitete Strings zurückzugeben", aber da dies der Abschnitt * consumer * ist, ist es klar, dass dies keine Auswirkungen auf die Implementierer hat. Was denkst du von diesem StringDecoder wird das nicht empfohlen? –

+0

Wenn Sie auch das verbrauchende Ende Ihres Transformations-Streams steuern, können Sie 'setEncoding' auf' process.stdin' aufrufen. –