如何将缓冲区包装为 stream2 可读流?

71

我该如何将node.js buffer转换为符合stream2接口的可读流?

我已经找到了这个答案和stream-buffers模块,但该模块基于stream1接口。

3个回答

182

最简单的方法可能是创建一个新的PassThrough流实例,并将数据推送到其中。当您将其传输到其他流时,数据将从第一个流中提取出来。

var stream = require('stream');

// Initiate the source
var bufferStream = new stream.PassThrough();

// Write your buffer
bufferStream.end(Buffer.from('Test data.'));

// Pipe it to something else  (i.e. stdout)
bufferStream.pipe(process.stdout)

12
除非node.js在内部进行这样的操作,否则此解决方案不会将缓冲区切成较小的块,因此对于某些管道目标可能不是最理想的。但是,如果你看一下,接受答案中的streamifier库也没有进行切片操作。因此,保持简单性是值得肯定的。 - natevw
3
我在想是否使用var bufferStream = stream.PassThrough();可以使代码后面的读者更清晰地理解意图呢? - natevw
1
另外,请注意,如果您的目标预计流在某个时刻结束,则可能需要调用 bufferStream.end() - natevw
8
不需要对缓冲区进行切片,因为streams2的内部代码会处理它(搜索"fromList",在这里)。 实际上,如果切片缓冲区,性能将更差,因为如果流需要读取的字节数大于缓冲区长度,则如果你对其进行了切片,则streams2将再次连接它们(在这里)。 - Gabriel Llamas
如何测试或设置分块的大小? - user4584267
显示剩余3条评论

36

正如natevw所建议的那样,使用stream.PassThrough更加惯用,最后用缓冲区end:

var buffer = new Buffer( 'foo' );
var bufferStream = new stream.PassThrough();
bufferStream.end( buffer );
bufferStream.pipe( process.stdout );

这也是在vinyl-fs中如何转换/管道化缓冲区的方法。


2
为什么要使用 end 结束整个缓冲区?并且在此处 end 为什么跟在 pipe 后面? - Startec
5
end(buffer) 就是 write(buffer) 加上 end()。我会结束流,因为它不再需要了。在这里,end/pipe 的顺序并不重要,因为当有一些处理器处理数据事件时(如管道),PassThrough 才开始发出数据。 - morris4
1
@Startec 不对缓冲区进行切片意味着减少开销。如果您的消费者无法处理大块数据,则可以使用某些东西来拆分块。 - binki

3

一种现代简单的方法,可在任何使用fs.createReadStream()的地方使用,但无需先将文件写入路径。

const {Duplex} = require('stream'); // Native Node Module 

function bufferToStream(myBuuffer) {
    let tmp = new Duplex();
    tmp.push(myBuuffer);
    tmp.push(null);
    return tmp;
}

const myReadableStream = bufferToStream(your_buffer);
  • myReadableStream 可以重复使用。
  • 缓存和流只存在于内存中,没有写入本地存储。
  • 当实际文件存储在某些云服务上,我们的 API 充当了中间人,我经常使用这种方法。文件永远不会被写入本地文件。
  • 我发现无论缓冲区大小(高达10 MB)或接受可读流的目标如何,这都是非常可靠的。更大的文件应该实现特定的方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接