根据 nodeJS docs(v5.10.0)对于可读流:
it is better to use
readable.setEncoding('utf8')
than working with buffers directly usingbuf.toString(encoding)
. This is because "multi-byte characters (...) would otherwise be potentially mangled. If you want to read the data as strings, always use this method.
我的问题是关于如何使用新的 Transform 流 API 来实现这一点。现在没有必要通过继承冗长的方法。
因此,例如,这可以作为一种将标准输入转换为大写字符串的方法
const transform = require("stream").Transform({
transform: function(chunk, encoding, next) {
this.push(chunk.toString().toUpperCase());
next();
}
});
process.stdin.pipe(transform).pipe(process.stdout);
但是,这似乎违背了不在缓冲区上使用 toString()
的建议。我尝试通过将编码设置为“utf-8”来修改 Transform 实例,如下所示:
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);
经检查,transform
在第一种情况下的编码为 null,而在第二种情况下它确实已更改为“utf-8”。然而,传递给转换函数的 block 仍然是一个缓冲区。我认为通过设置编码可以跳过 toString()
方法,但事实并非如此。
我也曾尝试像 Readable 和 Duplex 示例中那样扩展 read
方法,但这是不允许的。
有没有办法摆脱toString()
?
最佳答案
你是对的。直接在 _transform 方法中使用 Buffer#toString
是不好的。但是,setEncoding 旨在供可读流消费者 使用(即从您的转换流中读取的代码)。您正在实现 转换流。它不会为您更改 _transform 方法的输入。
在内部,可读流使用 StringDecoder如果消费者激活自动解码。您也可以在转换方法中使用它。
这是一个 code comment解释它是如何工作的:
[StringDecoder] decodes the given buffer and returns it as JS string that is guaranteed to not contain any partial multi-byte characters. Any partial character found at the end of the buffer is buffered up, and will be returned when calling write again with the remaining bytes.
因此,您的示例可以重写如下:
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);
关于javascript - 以安全的方式为 nodeJS 转换流设置编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36373486/