stream
模块的作用
在 Node.js 中,
stream
模块是一个用于处理流(stream)的核心模块。流是一种处理数据的抽象方式,允许程序处理大量数据时不会一次性将所有数据加载到内存中,从而提高性能和内存效率。通过流,Node.js 可以以分块的方式读取和写入数据,这对于处理大文件或实时数据流(如音视频流、网络请求等)非常有效。
流可以分为以下几种类型:
- Readable Streams:可读流,允许从某个数据源中读取数据(例如,文件、HTTP 响应、标准输入等)。
- Writable Streams:可写流,允许将数据写入某个目标(例如,文件、HTTP 请求、标准输出等)。
- Duplex Streams:双工流,既可以读也可以写(例如,网络通信中的 TCP 套接字)。
- Transform Streams:转换流,既可以读也可以写,但在读取数据时,会在读取的数据上执行一些转换操作(例如,压缩、加密、解密等)。
核心功能和概念
-
数据流的处理方式:
- 流是按块(chunk)进行传输的,避免了将所有数据一次性加载到内存中的问题。这使得在处理大数据时,程序能够以非常高效的方式进行工作。
- 流会自动地分配缓冲区,这些缓冲区的大小可以根据需求进行调节。
-
事件驱动:
- 流是基于事件驱动的。当数据可用时,会触发事件。常见的事件有
data
、end
、error
和finish
等。
- 流是基于事件驱动的。当数据可用时,会触发事件。常见的事件有
-
管道操作:
- Node.js 的
stream
模块支持管道(pipe)操作。你可以将一个流的输出连接到另一个流的输入,这样数据就能自动从一个流传输到另一个流,而不需要手动处理每个数据块。 stream.pipe()
是常用的流连接方法。
- Node.js 的
stream
模块相关的API
1、Readable Stream(可读流)
- 用途:用于从数据源中读取数据。
- 常见使用场景:读取文件、HTTP 请求响应、标准输入等。
javascript
const fs = require('fs');
const readableStream = fs.createReadStream('example.txt', { encoding: 'utf8' });
readableStream.on('data', (chunk) => {
console.log('Received chunk:', chunk);
});
readableStream.on('end', () => {
console.log('No more data.');
});
readableStream.on('error', (err) => {
console.error('Error:', err);
});
当读取一个文件时,打印的格式是以下这样的
2、Writable Stream(可写流)
- 用途:用于向某个目标写入数据。
- 常见使用场景:写入文件、HTTP 请求的响应、标准输出等。
javascript
const fs = require('fs');
const writableStream = fs.createWriteStream('output.txt');
writableStream.write('Hello, world!\n');
writableStream.end(); // 完成写入
writableStream.on('finish', () => {
console.log('Writing completed!');
});
writableStream.on('error', (err) => {
console.error('Error:', err);
});
3、Duplex Stream(双工流)
- 用途:可以同时读取和写入的流。
- 常见使用场景:例如,网络通信中的 TCP 套接字。
javascript
const { Duplex } = require('stream');
const duplexStream = new Duplex({
read(size) {
this.push('data from read\n');
this.push(null); // 结束流
},
write(chunk, encoding, callback) {
console.log('Received chunk:', chunk.toString());
callback();
}
});
duplexStream.write('Hello, Duplex stream!\n');
duplexStream.pipe(process.stdout);
4、Transform Stream(转换流)
- 用途:用于在读取数据时,对数据进行某种转换(例如,压缩、解密等)。
- 常见使用场景:压缩文件、数据加密等。
javascript
const { Transform } = require('stream');
const transformStream = new Transform({
transform(chunk, encoding, callback) {
this.push(chunk.toString().toUpperCase()); // 转换成大写
callback();
}
});
process.stdin.pipe(transformStream).pipe(process.stdout);
主要方法和事件
常用方法:
stream.read([size])
:从流中读取数据,size
参数控制每次读取的字节数。stream.write(chunk[, encoding][, callback])
:向流中写入数据。stream.end([chunk][, encoding][, callback])
:标记流的结束,通常在写入完毕后调用。stream.pipe(destination)
:将当前流的输出传递到目标流(即另一个流)。
常用事件:
'data'
:当可读取的数据时触发。'end'
:数据读取完毕时触发(在可读流中)。'finish'
:数据写入完毕时触发(在可写流中)。'error'
:流操作中发生错误时触发。