Node.js入门教程(十八):Stream(流)
一、什么是 StreamNode.js 的 Stream 是一种处理流式数据的抽象接口广泛应用于文件操作、网络通信等场景。流式数据处理的一个主要优点是可以在数据传输过程中就开始处理数据而不需要等待整个数据加载完毕这使得 Node.js 能够高效地处理大量数据而不会占用过多的内存。Stream 是一个抽象接口Node 中有很多对象实现了这个接口。例如对 http 服务器发起请求的request对象就是一个 Stream还有stdout标准输出。Node.js 的 Stream流允许你以流的形式处理数据而不是一次性将数据全部加载到内存中。这对于处理大量数据或者实现高效的数据传输非常有用。二、流的四种类型类型说明Readable可读流可读操作如文件读取流、网络请求响应流Writable可写流可写操作如文件写入流、网络请求发送流Duplex双工流可读可写操作如 TCP 套接字Transform转换流操作被写入数据然后读出结果如压缩/解压缩流常用事件所有的 Stream 对象都是EventEmitter的实例。常用的事件有事件说明data当有数据可读时触发end没有更多的数据可读时触发error在接收和写入过程中发生错误时触发finish所有数据已被写入到底层系统时触发三、从流中读取数据常见的可读流包括文件读取流和网络请求响应流。创建input.txt文件内容如下地址www.chenbyte.com创建main.js文件代码如下var fs require(fs); var data ; // 创建可读流 var readerStream fs.createReadStream(input.txt); // 设置编码为 utf8 readerStream.setEncoding(UTF8); // 处理流事件 -- data, end, and error readerStream.on(data, function(chunk) { data chunk; }); readerStream.on(end, function() { console.log(data); }); readerStream.on(error, function(err) { console.log(err.stack); }); console.log(程序执行完毕);以上代码执行结果如下程序执行完毕 地址www.chenbyte.com四、写入流可写流用于将数据写入目的地常见的可写流包括文件写入流和网络请求发送流。创建main.js文件代码如下var fs require(fs); var data 菜鸟教程官网地址www.runoob.com; // 创建一个可以写入的流写入到文件 output.txt 中 var writerStream fs.createWriteStream(output.txt); // 使用 utf8 编码写入数据 writerStream.write(data, UTF8); // 标记文件末尾 writerStream.end(); // 处理流事件 -- finish、error writerStream.on(finish, function() { console.log(写入完成。); }); writerStream.on(error, function(err) { console.log(err.stack); }); console.log(程序执行完毕);以上程序会将data变量的数据写入到output.txt文件中。代码执行结果如下$ node main.js 程序执行完毕 写入完成。查看output.txt文件的内容$ cat output.txt 地址www.chenbyte.com五、双工流Duplex双工流同时具有可读和可写的能力。一个典型的双工流是 TCP 套接字。const net require(net); // 创建一个 TCP 服务器 const server net.createServer((socket) { console.log(Client connected.); // 读取客户端数据 socket.on(data, (data) { console.log(Received data:, data.toString()); }); // 向客户端发送数据 socket.write(Hello, Client!\n); // 监听关闭事件 socket.on(end, () { console.log(Client disconnected.); }); }); server.listen(3000, () { console.log(Server listening on port 3000.); });六、转换流Transform转换流是一种特殊的双工流可以修改或转换数据。常见的转换流包括压缩和解压缩流。const zlib require(zlib); const fs require(fs); // 创建一个可读流 const readableStream fs.createReadStream(example.txt); // 创建一个转换流压缩 const gzip zlib.createGzip(); // 创建一个可写流 const writableStream fs.createWriteStream(example.txt.gz); // 将可读流管道到转换流再管道到可写流 readableStream.pipe(gzip).pipe(writableStream); // 监听完成事件 writableStream.on(finish, () { console.log(File compressed successfully.); });七、管道流Pipe管道提供了一个输出流到输入流的机制。通常我们用于从一个流中获取数据并将数据传递到另外一个流中。把文件比作装水的桶而水就是文件里的内容我们用一根管子pipe连接两个桶使得水从一个桶流入另一个桶这样就慢慢实现了大文件的复制过程。管道流操作实例设置input.txt文件内容如下菜鸟教程官网地址www.chenbyte.com创建main.js文件代码如下var fs require(fs); // 创建一个可读流 var readerStream fs.createReadStream(input.txt); // 创建一个可写流 var writerStream fs.createWriteStream(output.txt); // 管道读写操作 // 读取 input.txt 文件内容并将内容写入到 output.txt 文件中 readerStream.pipe(writerStream); console.log(程序执行完毕);代码执行结果如下$ node main.js 程序执行完毕查看output.txt文件的内容$ cat output.txt 地址www.chenbyte.com八、链式流链式是通过连接输出流到另外一个流并创建多个流操作链的机制。链式流一般用于管道操作。接下来我们使用管道和链式来压缩和解压文件。压缩文件创建compress.js文件代码如下var fs require(fs); var zlib require(zlib); // 压缩 input.txt 文件为 input.txt.gz fs.createReadStream(input.txt) .pipe(zlib.createGzip()) .pipe(fs.createWriteStream(input.txt.gz)); console.log(文件压缩完成。);代码执行结果如下$ node compress.js 文件压缩完成。执行完以上操作后可以看到当前目录下生成了input.txt的压缩文件input.txt.gz。解压文件创建decompress.js文件代码如下var fs require(fs); var zlib require(zlib); // 解压 input.txt.gz 文件为 input.txt fs.createReadStream(input.txt.gz) .pipe(zlib.createGunzip()) .pipe(fs.createWriteStream(input.txt)); console.log(文件解压完成。);代码执行结果如下$ node decompress.js 文件解压完成。九、暂停和恢复可读流可以暂停和恢复数据的读取。const fs require(fs); const readableStream fs.createReadStream(example.txt, utf8); readableStream.on(data, (chunk) { console.log(Received chunk:, chunk); readableStream.pause(); // 暂停读取 setTimeout(() { readableStream.resume(); // 恢复读取 }, 1000); });十、销毁流可以销毁流释放资源。const fs require(fs); const readableStream fs.createReadStream(example.txt, utf8); readableStream.on(data, (chunk) { console.log(Received chunk:, chunk); readableStream.destroy(); // 销毁流 });十一、流的主要方法方法说明readable.pipe(destination)将可读流的数据传输到可写流readable.on(data, callback)监听数据事件readable.on(end, callback)监听结束事件readable.pause()暂停可读流readable.resume()恢复可读流readable.destroy()销毁可读流writable.write(chunk)写入数据到可写流writable.end()结束写入writable.on(finish, callback)监听写入完成事件writable.on(error, callback)监听错误事件十二、本章小结知识点说明Stream 是什么处理流式数据的抽象接口高效处理大量数据四种流类型Readable可读、Writable可写、Duplex双工、Transform转换常用事件data、end、error、finish管道流pipe()方法将可读流连接到可写流链式流多个pipe()串联形成处理链压缩/解压使用zlib模块配合转换流实现控制流pause()、resume()、destroy()控制流的行为提示Stream 是 Node.js 高效处理 I/O 的核心机制。对于大文件处理、网络数据传输等场景使用 Stream 可以显著降低内存占用提升应用性能。管道流pipe是 Stream 中最常用的操作模式可以简洁地将数据从源头传递到目的地。