如何使用 Node.js 中的 fs 模块处理文件

作者选择了COVID-19 救济基金来接受捐赠,作为Write for DOnations计划的一部分。

介绍

处理文件对于开发目的和非开发目的一样普遍。在日常计算机使用中,用户可能会在各种目录中的文件中读取和写入数据,以完成诸如保存下载的文件或访问要在其他应用程序中使用的数据等任务。同样,后端程序或命令行界面 (CLI) 工具可能需要将下载的数据写入文件以进行保存,或者数据密集型应用程序可能需要导出为JSONCSVExcel格式。这些程序需要与运行它们的操作系统的文件系统进行通信。

使用Node.js,您可以使用内置fs模块以编程方式操作文件该名称是“文件系统”的缩写,该模块包含您在本地机器上读取、写入和删除文件所需的所有功能。Node.js 的这一独特方面使JavaScript成为用于后端和 CLI 工具编程的有用语言。

在本文中,您将使用该fs模块读取通过命令行创建的文件,创建并写入新文件,删除您创建的文件,并将第一个文件移动到不同的文件夹中。fs模块支持同步、异步或通过流与文件交互;本教程将重点介绍如何使用异步的、基于Promise的 API,这是 Node.js 开发人员最常用的方法。

先决条件

步骤 1 — 读取文件 readFile()

在这一步中,您将编写一个程序来读取 Node.js 中的文件。为此,您需要导入fs模块,这是一个用于处理文件的标准 Node.js 模块,然后使用该模块的readFile()功能。您的程序将读取该文件,将其内容存储在一个变量中,然后将其内容记录到控制台。

第一步是为此活动和后面部分中的环境设置编码环境。

创建一个文件夹来存储您的代码。在您的终端中,创建一个名为 的文件夹node-files

  • mkdir node-files

使用以下cd命令将您的工作目录更改为新创建的文件夹

  • cd node-files

在此文件夹中,您将创建两个文件。第一个文件将是一个新文件,其中包含您的程序稍后将读取的内容。第二个文件将是读取文件的 Node.js 模块。

greetings.txt使用以下命令创建文件

  • echo "hello, hola, bonjour, hallo" > greetings.txt

echo命令将其字符串参数打印到终端。您可以使用>重定向 echo的输出到一个新的文件,greetings.txt

现在,readFile.js在您选择的文本编辑器中创建并打开本教程使用nano,一个终端文本编辑器。你可以这样打开这个文件nano

  • nano readFile.js

该文件的代码可以分为三个部分。首先,您需要导入允许您的程序处理文件Node.js 模块在您的文本编辑器中,输入以下代码:

节点文件/readFile.js
const fs = require('fs').promises;

如前所述,您使用该fs模块与文件系统进行交互。但是请注意,您正在导入.promises模块一部分。

fs首次创建模块,写在Node.js的异步代码的主要方式是通过回调随着 Promise 越来越流行,Node.js 团队致力于在fs开箱即用的模块中支持它们在 Node.js 版本 10 中,他们在使用 Promisepromisesfs模块中创建了一个对象,而主fs模块继续公开使用回调的函数。在此程序中,您将导入模块的 promise 版本。

导入模块后,您可以创建一个异步函数来读取文件。异步函数以async关键字开头使用异步函数,您可以使用await关键字解析承诺,而不是将承诺与.then()方法链接起来

创建一个readFile()接受一个参数的新函数,一个名为 的字符串filePath您的readFile()函数将使用fs模块使用async/await语法将文件加载到变量中

输入以下突出显示的代码:

节点文件/readFile.js
const fs = require('fs').promises;

async function readFile(filePath) {
  try {
    const data = await fs.readFile(filePath);
    console.log(data.toString());
  } catch (error) {
    console.error(`Got an error trying to read the file: ${error.message}`);
  }
}

async可以使用关键字定义函数,以便以后可以使用伴随的await关键字。要捕获异步文件读取操作中的错误,请fs.readFile()使用try...catchblock将调用括起来在该try部分中,您data使用该fs.readFile()函数将文件加载到变量中该函数唯一需要的参数是文件路径,它以字符串形式给出。

fs.readFile()返回buffer的默认对象。一个buffer对象可以存储任何类型的文件。当您记录文件的内容时,您可以使用toString()缓冲区对象方法将这些字节转换为文本

如果捕获到错误,通常是未找到文件或程序没有读取文件的权限,则会在控制台中记录收到的错误。

最后,greetings.txt使用以下突出显示的行调用文件上的函数

节点文件/readFile.js
const fs = require('fs').promises;

async function readFile(filePath) {
  try {
    const data = await fs.readFile(filePath);
    console.log(data.toString());
  } catch (error) {
    console.error(`Got an error trying to read the file: ${error.message}`);
  }
}

readFile('greetings.txt');

请务必保存您的内容。使用nano,您可以按 保存并退出CTRL+X

您的程序现在将读取greetings.txt您之前创建文件并将其内容记录到终端。通过使用以下命令执行您的模块来确认这一点node

  • node readFile.js

您将收到以下输出:

Output
hello, hola, bonjour, hallo

您现在已经使用语法读取了包含fs模块readFile()函数的文件async/await

注意:在一些较早版本的 Node.js 中,使用fs模块时会收到以下警告

(node:13085) ExperimentalWarning: The fs.promises API is experimental

模块promises对象fs是在 Node.js 版本 10 中引入的,所以一些早期版本仍然称模块为实验性的。当 API 在版本 12.6 中变得稳定时,此警告被删除。

现在您已经使用fs模块读取了一个文件,接下来您将创建一个文件并向其中写入文本。

第 2 步 — 用 writeFile()

在这一步中,您将编写具有模块writeFile()功能的文件fs您将在 Node.js 中创建一个 CSV 文件来跟踪杂货账单。第一次写入文件时,您将创建文件并添加标题。第二次,您将数据附加到文件中。

在文本编辑器中打开一个新文件:

  • nano writeFile.js

通过导入fs模块开始您的代码

节点文件/writeFile.js
const fs = require('fs').promises;

async/await在创建两个函数时,您将继续使用语法。第一个功能是制作 CSV 文件。第二个功能是将数据添加到 CSV 文件。

在文本编辑器中,输入以下突出显示的代码:

节点文件/writeFile.js
const fs = require('fs').promises;

async function openFile() {
  try {
    const csvHeaders = 'name,quantity,price'
    await fs.writeFile('groceries.csv', csvHeaders);
  } catch (error) {
    console.error(`Got an error trying to write to a file: ${error.message}`);
  }
}

此异步函数首先创建一个csvHeaders包含 CSV 文件列标题的变量。然后使用该模块writeFile()功能fs创建一个文件并向其中写入数据。第一个参数是文件路径。由于您只提供了文件名,Node.js 将在您执行代码的同一目录中创建文件。第二个参数是您正在写入的数据,在本例中为csvHeaders变量。

接下来,创建一个新函数以将项目添加到您的购物清单。在文本编辑器中添加以下突出显示的函数:

节点文件/writeFile.js
const fs = require('fs').promises;

async function openFile() {
  try {
    const csvHeaders = 'name,quantity,price'
    await fs.writeFile('groceries.csv', csvHeaders);
  } catch (error) {
    console.error(`Got an error trying to write to a file: ${error.message}`);
  }
}

async function addGroceryItem(name, quantity, price) {
  try {
    const csvLine = `\n${name},${quantity},${price}`
    await fs.writeFile('groceries.csv', csvLine, { flag: 'a' });
  } catch (error) {
    console.error(`Got an error trying to write to a file: ${error.message}`);
  }
}

异步addGroceryItem()函数接受三个参数:杂货商品的名称、您购买的数量和单位价格。这些参数与模板文字语法一起使用以形成csvLine变量,即您要写入文件的数据。

然后writeFile()像在openFile()函数中一样使用该方法然而,这次你有第三个参数:一个JavaScript 对象这个对象有一个flag值为a标志告诉 Node.js 如何与系统上的文件交互。通过使用 flag a,您是在告诉 Node.js 附加到文件中,而不是覆盖它。如果您不指定标志,则默认为w,如果不存在则创建一个新文件,如果文件已存在则覆盖该文件。您可以在Node.js 文档 中了解有关文件系统标志的更多信息

要完成您的脚本,请使用这些函数。在文件末尾添加以下突出显示的行:

节点文件/writeFile.js
...
async function addGroceryItem(name, quantity, price) {
  try {
    const csvLine = `\n${name},${quantity},${price}`
    await fs.writeFile('groceries.csv', csvLine, { flag: 'a' });
  } catch (error) {
    console.error(`Got an error trying to write to a file: ${error.message}`);
  }
}

(async function () {
  await openFile();
  await addGroceryItem('eggs', 12, 1.50);
  await addGroceryItem('nutella', 1, 4);
})();

要调用这些函数,首先要使用async function. 由于在await撰写本教程时无法在全局范围内使用关键字,因此您必须将异步函数包装在async function. 请注意,此函数是匿名的,这意味着它没有名称来识别它。

您的openFile()addGroceryItem()函数是异步函数。如果不将这些调用包含在另一个函数中,则无法保证内容的顺序。您创建的包装器是用async关键字定义的在该函数中,您可以使用await关键字对函数调用进行排序

最后,async function定义被括在括号中。它们告诉 JavaScript,它们内部的代码是一个函数表达式。函数末尾和分号之前的括号用于立即调用函数。这称为立即调用函数表达式(IIFE)通过使用带有匿名函数的 IIFE,您可以测试您的代码是否生成了一个包含三行的 CSV 文件:列标题、一行用于eggs,最后一行用于nutella

保存并退出nanoCTRL+X

现在,使用以下node命令运行您的代码

  • node writeFile.js

不会有输出。但是,您的当前目录中将存在一个新文件。

使用cat命令显示内容groceries.csv

  • cat groceries.csv

您将收到以下输出:

节点文件/groceries.csv
name,quantity,price
eggs,12,1.5
nutella,1,4

您的调用openFile()创建了一个新文件并为您的 CSV 添加了列标题。随后的调用addGroceryItem()添加了您的两行数据。

使用该writeFile()功能,您可以创建和编辑文件。接下来,您将删除文件,这是当您有临时文件或需要在硬盘驱动器上腾出空间时的常见操作。

在这一步中,您将删除模块中具有该unlink()功能的文件fs您将编写一个 Node.js 脚本来删除groceries.csv您在上一节中创建文件。

在您的终端中,为此 Node.js 模块创建一个新文件:

  • nano deleteFile.js

现在您将编写创建异步deleteFile()函数的代码该函数将接受一个文件路径作为参数,将其传递给unlink()函数以将其从文件系统中删除。

在您的文本编辑器中,编写以下代码:

节点文件/deleteFile.js
const fs = require('fs').promises;

async function deleteFile(filePath) {
  try {
    await fs.unlink(filePath);
    console.log(`Deleted ${filePath}`);
  } catch (error) {
    console.error(`Got an error trying to delete the file: ${error.message}`);
  }
}

deleteFile('groceries.csv');

unlink()函数接受一个参数:要删除的文件的文件路径。

警告:当您使用该unlink()功能删除文件时,它不会发送到您的回收站或垃圾桶,而是从您的文件系统中永久删除。此操作不可逆,因此请确保在执行代码之前要删除该文件。

退出nano,确保通过输入保存文件的内容CTRL+X

现在,执行程序。在终端中运行以下命令:

  • node deleteFile.js

您将收到以下输出:

Output
Deleted groceries.csv

要确认该文件不再存在,请ls在当前目录中使用以下命令:

  • ls

此命令将显示这些文件:

Output
deleteFile.js greetings.txt readFile.js writeFile.js

您现在已经确认您的文件已使用该unlink()功能删除

到目前为止,您已经学习了如何读取、写入、编辑和删除文件。以下部分使用一个函数将文件移动到不同的文件夹。学习该功能后,您将能够在 Node.js 中执行最关键的文件管理任务。

第 4 步 — 移动文件 rename()

文件夹用于组织文件,因此能够以编程方式将文件从一个文件夹移动到另一个文件夹使文件管理更容易。您可以使用该rename()函数在 Node.js 中移动文件在此步骤中,您会将greetings.txt文件的副本移动到新文件夹中。

在对 Node.js 模块进行编码之前,您需要进行一些设置。首先创建一个文件夹,您要将文件移动到该文件夹​​中。在终端中,test-data在当前目录中创建一个文件夹:

  • mkdir test-data

现在,greetings.txt使用以下cp命令复制第一步中使用的文件

  • cp greetings.txt greetings-2.txt

通过打开 JavaScript 文件来包含您的代码来完成设置:

  • nano moveFile.js

在您的 Node.js 模块中,您将创建一个moveFile()调用该rename()函数的函数。使用该rename()功能时,需要提供原文件的文件路径和目标位置的路径。对于此示例,您将使用moveFile()函数将greetings-2.txt文件移动到文件test-data夹中。您还将其名称更改为salutations.txt.

在打开的文本编辑器中输入以下代码:

节点文件/moveFile.js
const fs = require('fs').promises;

async function moveFile(source, destination) {
  try {
    await fs.rename(source, destination);
    console.log(`Moved file from ${source} to ${destination}`);
  } catch (error) {
    console.error(`Got an error trying to move the file: ${error.message}`);
  }
}

moveFile('greetings-2.txt', 'test-data/salutations.txt');

如前所述,该rename()函数采用两个参数:源文件路径和目标文件路径。此功能可以将文件移动到其他文件夹,重命名当前目录中的文件,或同时移动和重命名。在您的代码中,您正在移动和重命名您的文件。

nano保存并退出CTRL+X

接下来,使用node. 输入此命令以运行程序:

  • node moveFile.js

您将收到此输出:

Output
Moved file from greetings-2.txt to test-data/salutations.txt

要确认当前目录中不再存在该文件,您可以使用以下ls命令:

  • ls

此命令将显示这些文件和文件夹:

Output
deleteFile.js greetings.txt moveFile.js readFile.js test-data writeFile.js

您现在可以使用ls列出test-data子文件夹中的文件:

  • ls test-data

您移动的文件将出现在输出中:

Output
salutations.txt

您现在已经使用该rename()函数将文件从当前目录移动到子文件夹中。您还使用相同的函数调用重命名了该文件。

结论

在本文中,您学习了使用 Node.js 管理文件的各种功能。您首先使用readFile(). 然后,您使用该writeFile()函数创建了新文件并将数据附加到现有文件中您使用该unlink()函数永久删除了一个文件,然后使用rename().

以编程方式处理文件是 Node.js 的一项重要功能。程序可能需要输出文件供用户使用,或者可能需要为不总是运行的应用程序存储数据。借助fs模块的功能,开发人员可以控制在我们的 Node.js 程序中如何使用文件。

要了解有关该fs模块的更多信息,您可以阅读Node.js 文档如果您想继续学习 Node.js,可以返回到如何在 Node.js 中编码系列,或在我们的Node 主题页面浏览编程项目和设置

觉得文章有用?

点个广告表达一下你的爱意吧 !😁