Node.js - Streams



什么是流(Streams)?

流是数据的集合。但是,与数组或字符串不同,流对象中的所有数据不会立即存储在内存中。取而代之的是,流中的单个数据块一次被引入内存。它使流更加高效。Node.js应用程序最适合开发数据流应用程序。

流的类型

Node.js处理四种基本类型的流 -

  • Writable - 可以写入数据的流。
  • Readable - 可以从中读取数据的流。
  • Duplex - 既可读又可写的流。
  • Transform - 可以在写入和读取数据时修改或转换数据的双工流。

每种类型的 Stream 都是一个 EventEmitter 实例,并在不同的实例时间抛出多个事件。例如,一些常用的事件是 -

  • data − 当有数据可供读取时,将触发此事件。
  • end − 当没有更多数据可读取时触发此事件。
  • error − 当接收或写入数据时出现任何错误时,将触发此事件。
  • finish − 当所有数据都已刷新到底层系统时,将触发此事件。

本章中的示例使用名为 input.text 的文件,其中包含以下数据。

qikepu.com is giving self learning content
to teach the world in simple and easy way!!!!!

Readable 流

文件对象充当流,可以从中读取特定大小的块中的数据。在以下示例中,我们从 fs 模块调用 createReadStream() 函数来从给定文件中读取数据。可读流的 on 事件收集文件内容,直到触发 end 事件。


var fs = require("fs");
var data = '';

// 创建可读流
var readerStream = fs.createReadStream('input.txt');

// 将编码设置为utf8
readerStream.setEncoding('UTF8');

// 处理流事件-->数据、结束和错误
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("Program Ended");

将上述脚本另存为main.js。运行上述Node.js应用程序。它将显示 input.text 文件的内容。

Writable 流

fs 模块中的 createWriteStream() 函数创建一个 Writable 流对象。它的 write() 方法将数据存储在作为参数提供给 createWriteStream() 函数的文件中。

使用main.js作为其名称保存以下代码。


var fs = require("fs");
var data = `qikepu.com is giving self learning content
to teach the world in simple and easy way!!!!!`;

// 创建可写流
var writerStream = fs.createWriteStream('output.txt');

// 将数据写入流,编码为utf8
writerStream.write(data,'UTF8');

// 标记文件结束
writerStream.end();

// 处理流事件-->完成和错误
writerStream.on('finish', function() {
	 	console.log("Write completed.");
});

writerStream.on('error', function(err){
	 	console.log(err.stack);
});

console.log("Program Ended");

现在打开在当前目录中创建output.txt,检查它是否包含给定的数据。

Piping 流

Piping 是一种机制,我们将一个流的输出作为另一个流的输入提供。它通常用于从一个流获取数据,并将该流的输出传递给另一个流。Piping 操作没有限制。现在,我们将展示一个管道示例,用于从一个文件读取并将其写入另一个文件。

使用以下代码创建名为 main.js 的 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("Program Ended");

现在运行main.js以查看结果 -

node main.js

验证输出。

Program Ended

打开在当前目录中创建output.txt;它应包含以下内容 -

qikepu.com is giving self learning content
to teach the world in simple and easy way!!!!!

Chaining 流

Chaining 是一种机制,用于将一个流的输出连接到另一个流,并创建多个流操作的Chaining 。它通常与 Piping 操作一起使用。现在,我们将使用 Piping 和 Chaining 首先压缩文件,然后解压缩相同的文件。

使用以下代码创建名为 main.js 的 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("File Compressed.");

现在运行main.js以查看结果 -

node main.js

验证输出。

File Compressed.

您会发现input.txt已被压缩,并在当前目录中input.txt.gz创建了一个文件。现在,让我们尝试使用以下代码解压缩同一文件 -


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("File Decompressed.");

现在运行main.js以查看结果 -

node main.js

验证输出。

File Decompressed.