根据nodeJS docs(v5.10.0)获取可读流:
最好使用
readable.setEncoding('utf8')
而不是使用 使用buf.toString(encoding)
直接缓冲。这是因为 "多字节字符(...)否则可能会被破坏。 如果要将数据作为字符串读取,请始终使用此方法。
我的问题是如何使用转换流的新API实现这一点。现在不需要通过继承详细方法。
因此,例如,这可以作为将stdin转换为大写字符串
的方法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"。然而,传递给transform函数的块仍然是缓冲区。我认为通过设置编码toString()
方法可以跳过,但事实并非如此。
我也尝试过扩展read
方法,如可读和双工示例,但这是不允许的。
有没有办法摆脱toString()
?
答案 0 :(得分:1)
你是对的。在_transform方法中直接使用Buffer#toString
是不好的。但是,setEncoding应由可读流使用者(即从转换流中读取的代码)使用。您正在实施转换流。它不会为您改变_transform方法的输入。
如果消费者激活自动解码,则内部可读流使用StringDecoder。您也可以在转换方法中使用它。
这是code comment解释它的工作原理:
[StringDecoder]解码给定的缓冲区并将其作为JS字符串返回,保证不包含任何部分多字节字符。在缓冲区末尾找到的任何部分字符都被缓冲,并在使用剩余字节再次调用write时返回。
所以,你的例子可以改写如下:
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);
答案 1 :(得分:0)
将' decodeStrings:false '作为' options '属性传递给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(); }, decodeStrings: false });