Node.js 流教程:文件流、管道

Node.js 中的文件流

Node.js 将流广泛用作数据传输机制。

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

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

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

Node.js 教程

简介

事件

生成器

数据连接

使用 Jasmine

步骤 2) 编写相关代码,利用流从文件中读取数据。

Filestream in Node.js

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. stream.on 函数是一个事件处理程序,我们在其中将第一个参数指定为“data”。这意味着每当数据从文件中进入流时,都会执行一个回调函数。在我们的例子中,我们定义了一个回调函数,它将执行 2 个基本步骤。第一个是将从文件中读取的数据转换为字符串。第二个是将转换后的字符串作为输出发送到控制台。
  4. 我们正在获取从数据流读取的每个数据块,并将其转换为字符串。
  5. 最后,我们将每个字符串转换块的输出发送到控制台。

输出

Filestream in Node.js

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

写入文件

与创建读流一样,我们也可以创建写流来将数据写入文件。让我们首先创建一个名为 data.txt 的空文件,其中不包含任何内容。假设此文件放在我们计算机的 D 盘上。

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

Filestream in Node.js

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 文件,您现在将在文件中看到以下数据

Node.js 教程

简介

事件

生成器

数据连接

使用 Jasmine

Node.js 中的管道

在 Node.js 应用程序中,可以使用 pipe() 方法将流管道连接在一起,该方法接受两个参数

  • 一个必需的可写流,作为数据目的地
  • 一个可选对象,用于传递选项。

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

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

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

Node.js 教程

简介

事件

生成器

数据连接

使用 Jasmine

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

步骤 3) 编写以下代码以将数据从 datainput.txt 文件传输到 dataOutput.txt 文件。

Pipes in Node.js

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 命令将数据从 readstream 传输到 write stream。pipe 命令将获取进入 readstream 的所有数据,并将其推送到 writestream。

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

Node.js 中的事件

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

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

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

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

Events in Node.js

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 中定义的 callback 函数。
  3. 我们定义了一个事件驱动的函数,该函数表示如果触发了“data_received”事件,则我们应该将“data_received”文本输出到控制台。
  4. 最后,我们使用 eventEmiter.emit 函数手动触发事件。这将触发 data_received 事件。

运行程序时,控制台中将显示“data received”文本,如下所示。

Events in Node.js

触发事件

在定义事件时,有各种可以调用的事件方法。本主题侧重于详细查看其中的每一种。

  1. 一次性事件处理程序

有时您可能只对事件发生的第一次做出反应感兴趣。在这些情况下,您可以使用 once() 方法。

让我们看看如何利用 once 方法来处理事件。

Emitting Events

代码解释:

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

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

  1. 检查事件监听器

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

如果您只对确定已附加监听器的数量感兴趣,那么别无他求,EventEmitter.listenerCount() 方法就是答案。

(注意: 监听器很重要,因为主程序应该知道监听器是否在运行时添加到事件上,否则程序会发生故障,因为附加的监听器将被调用。)

Emitting Events

代码解释:

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

如果代码执行正确,控制台将显示值 2。

  1. newListener 事件

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

Emitting Events

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”事件创建一个新的事件处理程序。因此,每当注册新的事件处理程序时,“Added listener for”+事件名称的文本将在控制台中显示。
  2. 在这里,我们为每个注册的事件将“Added listener for”+事件名称的文本写入控制台。
  3. 我们为“data_received”事件定义了 2 个事件处理程序。

如果上述代码执行正确,控制台中将显示以下文本。它仅显示“newListener”事件处理程序触发了两次。

为 data_received 事件添加了监听器

为 data_received 事件添加了监听器

摘要

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