Node.js Streams 教程:文件流,管道

在本教程中,你将学习

Node.js 中的 Filestream

Node 广泛使用流作为数据传输机制。

例如,当你使用 console.log 函数向控制台输出任何内容时,实际上是使用流将数据发送到控制台。

Node.js 还能够从文件中流式传输数据,以便可以对文件进行适当的读写。我们现在看一个如何使用流来读取和写入文件的示例。对于此示例,我们需要遵循下面提到的步骤

步骤 1: 创建一个名为 data.txt 的文件,其中包含以下数据。假设此文件存储在本地计算机的 D 盘上。

Tutorial on Node.js
Introduction
Events
Generators
Data Connectivity
Using Jasmine

步骤 2: 编写将使用流来从文件中读取数据的相关代码。

var fs = require("fs");
var stream;
stream = fs.createReadStream("D://data.txt");
stream.on("data", function(data) {
    var chunk = data.toString();
    console.log(chunk);
}); 

代码说明: -

  1. 我们首先需要包含 fs 模块,其中包含创建流所需的所有功能。
  2. 接下来,我们使用方法 createReadStream 创建可读流。作为输入,我们给出 data.txt 文件的位置。
  3. steam.on 函数是一个事件处理程序,在其中,我们将第一个参数指定为 data。这意味着只要数据来自文件的流,然后执行回调函数。在我们的例子中,我们定义了一个回调函数,它将执行 2 个基本步骤。第一种是将从文件读取的数据转换为字符串。第二种方法是将转换后的字符串作为输出发送到控制台。
  4. 我们将从数据流中读取每个数据块并将其转换为字符串。
  5. 最后,我们将每个字符串转换块的输出发送到控制台。

输出:

Tutorial on Node.js
Introduction
Events
Generators
Data Connectivity
Using Jasmine

如果代码执行正确,你将在控制台中看到上述输出。此输出将与 data.txt 文件中的输出相同。

写入文件

以同样的方式,我们创建一个读取流,我们也可以创建一个写入流来将数据写入文件。让我们首先创建一个没有名为 data.txt 的内容的空文件。我们假设这个文件放在我们电脑的 D 盘中。

以下代码显示了我们如何将数据写入文件。

var fs = require("fs");
var stream;
stream = fs.createWriteStream("D://data.txt");
stream.write("Tutorial on Node.js")
stream.write("Introduction")
stream.write("Events")
stream.write("Generators")
stream.write("Data Connectivity")
stream.write("Using Jasmine") 

代码说明: -

  1. 我们使用方法 createWriteStream 创建可写流。作为输入,我们给出 data.txt 文件的位置。
  2. 接下来,我们使用 stream.write 方法将不同的文本行写入文本文件。流将负责将此数据写入 data.txt 文件。

如果打开 data.txt 文件,现在将在文件中看到以下数据

Tutorial on Node.js
Introduction
Events
Generators
Data Connectivity
Using Jasmine

Node.js 中的管道

在 Node 应用程序中,可以使用 pipe() 方法将流连接在一起,该方法有两个参数:

  • 作为数据和目标的必需可写流
  • 用于传入选项的可选对象。

如果要将数据从一个文件传输到另一个文件,则使用管道的典型示例。

那么让我们看一个如何使用管道将数据从一个文件传输到另一个文件的示例。

步骤 1: 创建一个名为 datainput.txt 的文件,其中包含以下数据。假设此文件存储在本地计算机的 D 驱动器上。

Tutorial on Node.js
Introduction
Events
Generators
Data Connectivity
Using Jasmine

步骤 2: 创建一个名为 dataOutput.txt 的空白空文件,并将其放在本地计算机的 D 驱动器上。

步骤 3: 编写以下代码以执行从 datainput.txt 文件到 dataOutput.txt 文件的数据传输。

var fs = require("fs"); 
var readstream = fs.createReadStream("D://datainput.txt");

var writeStream = fs.createWriteStream("D://dataoutput.txt");

readstream.pipe(writeStream);

代码说明: -

  1. 我们首先为 datainput.txt 文件创建一个 readstream,其中包含我们需要传输到新文件的所有数据。
  2. 然后,我们需要为 dataOutput.txt 文件创建一个 writestream,这是我们的空文件,是从 datainput.txt 文件传输数据的目的地。
  3. 然后,我们使用 pipe 命令将数据从读取流传输到写入流。pipe 命令将获取进入读取流的所有数据,并将其推送到写入流。

如果现在打开 dataOutput.txt 文件,你将看到 datainput.txt 文件中存在的所有数据。

Node.js 中的事件

事件是 Node.js 中的关键概念之一,有时 Node.js 被称为事件驱动框架。

基本上,事件就是发生的事情。例如,如果建立与数据库的连接,则触发数据库连接事件。事件驱动编程是为了创建在触发特定事件时触发的函数。

让我们看一下在 Node.js 中定义事件的基本示例。

我们将创建一个名为 data_received 的事件。触发此事件时,文本 data_received 将发送到控制台。

var events = require('events');
var eventEmitter = new events.EventEmitter();
eventEmitter.on('data_received', function() {
    console.log('data received succesfully.');
});
eventEmitter.emit('data_received'); 

代码说明: -

  1. 使用 require 函数包含 events 模块。使用此模块,你将能够在 Node.js 中创建事件。
  2. 创建一个新的事件发射器。这用于绑定事件,在我们的例子中是 data_received 到在步骤 3 中定义的回调函数。
  3. 我们定义一个事件驱动函数,该函数表示如果触发 data_received 事件,则应将文本 data_received 输出到控制台。
  4. 最后,我们使用 eventEmiter.emit 函数手动触发事件。这将触发 data_received 事件。

程序运行时,文本 data received successfully 将发送到控制台。

发送事件

定义事件时,可以调用的事件有不同的方法。本主题重点介绍每个细节。

一次性事件处理程序

有时你可能只对第一次事件做出反应。在这些情况下,你可以使用 once() 方法。

让我们看看我们如何使用事件处理程序的 once 方法。

var events = require('events');
var eventEmitter = new events.EventEmitter();

eventEmitter.once('data received', function() {
	console.log('data received succesfully.');
});

eventEmitter.emit('data received');

eventEmitter.emit('data received');

代码说明: -

  1. 这里我们使用 once 方法来表示对于 data_received 事件,回调函数应该只执行一次。
  2. 我们在这里手动触发 data_received 事件。
  3. 当再次触发 data_received 事件时,此时不会发生任何事情。这是因为我们说第一步只能触发一次事件。

如果代码执行正确,则日志中的输出将为 data_received successfully。此消息仅在控制台中出现一次。

检查事件侦听器

在其生命周期的任何时刻,事件发射器可以附加零个或多个侦听器。可以通过多种方式检查每种事件类型的侦听器。

如果你只想确定附加侦听器的数量,那么只需查看 EventEmitter.listenerCount() 方法即可。

注意: Listeners 很重要,因为主程序应该知道是否正在动态添加监听器,否则程序会因为额外的监听器被调用而出现故障。)

var events = require('events')
var event Emitter = events.EventEmitter,
var emitter = new eventEmitter();

emitter.on('data received', function() {}); emitter.on('data received', function () {});
emitter.on ('data received", function(33; er

console.log(eventEmitter.listenerCount(emitter, "data received"));

代码说明: -

  1. 我们正在定义一个 eventEmitter 类型,它是使用与事件相关的方法所必需的。
  2. 然后我们定义一个名为 emitter 的对象,它将用于定义我们的事件处理程序。
  3. 我们正在创建 2 个事件处理程序,基本上什么都不做。为了展示 listenerCount 方法的工作原理,我们的示例保持简单。
  4. 现在,当你在 data_received 事件上调用 listenerCount 方法时,它将在控制台日志中发送附加到此事件的事件侦听器数。

如果代码执行正确,则 2 将显示在控制台日志中。

newListener Event

每次注册新的事件处理程序时,事件发射器都会发出 newListener 事件。此事件用于检测新事件处理程序。当你需要为每个新事件处理程序分配资源或执行某些操作时,通常使用 newListener 事件。

var events = require('events');
var eventEmitter = events.EventEmitter;
var emitter = new eventEmitter();
emitter.on("newListener", function(eventName, listener) {
    console.log("Added listener for " + eventName + " events");
});
emitter.on('data_received', function() {});
emitter.on('data_received', function() {}); 

代码说明: -

  1. 我们正在为 newListener 事件创建一个新的事件处理程序。因此,每当注册新的事件处理程序时,将在控制台中显示文本 已添加的侦听器+事件名称。
  2. 在这里,我们正在向控制台写入 已添加侦听器 文本+已注册的每个事件的事件名称。
  3. 我们为事件 data_received 定义了 2 个事件处理程序。

如果上面的代码执行正确,下面的文本将显示在控制台中。它只显示 newListener 事件处理程序被触发两次。

Added listener for data_received events

Added listener for data_received events

摘要

  • 在 Node.js 中使用流来从输入 - 输出设备读取和写入数据。Node.js 利用 fs 库为文件创建可读写的流。这些流可用于从文件读取和写入数据。
  • 管道可用于将多个流连接在一起。最常见的示例之一是将读取和写入流一起管道,以便将数据从一个文件传输到另一个文件。
  • Node.js 通常也被标记为事件驱动框架,并且在 Node.js 中定义事件非常容易。可以定义响应这些事件的函数。
  • 事件还公开了响应关键事件的方法。例如,我们已经看到了 once() 事件处理程序,它可以用来确保只在触发事件时执行一次回调函数。