node.js 中管道和流的区别

Kan*_*n-0 7 javascript pipe stream fs node.js

这是我的代码

const fs = require('fs');
const src = fs.createReadStream('bigfile3.txt');
const des = fs.createWriteStream('newTest.txt');
Run Code Online (Sandbox Code Playgroud)

我可以使用

src.on('data',(chunk)=>{
des.write(chunk);});
Run Code Online (Sandbox Code Playgroud)

或者

src.pipe(des);
Run Code Online (Sandbox Code Playgroud)

这两种处理文件操作的方式有什么区别吗?> "size" argument must not be larger than 2147483647每当我尝试使用大文件时,管道方法都会给我一个错误 。(~2GB)

谁能解释管道和流背后的工作?谢谢。

San*_*ket 6

您应该使用管道方法,因为数据流将被自动管理,以便目标可写流不会被更快的可读流淹没。

如果您的可读流比可写流快,那么您可能会在des.write(data)方法中遇到数据丢失,因此最好使用src.pipe(des);

如果文件大小很大,那么你应该使用流,这是正确的方法,我尝试了像你这样的类似示例,使用流和管道复制 3.5 GB 文件,在我的情况下它工作完美。检查一下你一定做错了什么。

我尝试过的例子

'use strict'

const fs =require('fs')
const readStream = fs.createReadStream('./Archive.zip')
const writeStream = fs.createWriteStream('./Archive3.zip')


readStream.pipe(writeStream)
Run Code Online (Sandbox Code Playgroud)

但是,如果您仍然需要使用 Stream des.write(data),您可以在速度更快时处理背压以避免数据丢失readStream。如果来自的响应des.write(data)false,则已writeStream加载,暂停 readStream src.pause()

要在writeStream耗尽时继续,请处理drainwriteStream 上的事件并在回调中恢复。

des.on("drain", () => src.resume())
Run Code Online (Sandbox Code Playgroud)

要允许更高的 writeStream 缓冲区内存,您可以将highWaterMarkfor设置readStream为非常高的值,例如

const des = fs.createWriteStream('newTest.txt',{
     highWaterMark: 1628920128
});
Run Code Online (Sandbox Code Playgroud)

小心太大,highWaterMark因为这会占用太多内存并破坏流数据的主要优势。

我肯定仍然会推荐使用,pipe因为它可以用更少的代码为您处理所有事情。

文件:

https://nodejs.org/api/stream.html#stream_writable_write_chunk_encoding_callback

https://nodejs.org/api/stream.html#stream_read_pipe_destination_options