Node.js 文件系统 API - 初学者友好指南 文件系统 API 异步特性 阅读 写作 暂停

2025-06-08

Node.js 文件系统 API - 初学者友好指南

文件系统API

异步特性

阅读

写作

暂停

这篇文章取自我的博客,所以一定要查看它以获取更多最新内容😉

继续“ Node.js 内幕揭秘! ”系列,今天我们将深入探讨文件系统 API——它是 Node.js 中最强大的 API 之一!需要注意的是,我们使用的是 Node.js LTS v10.15.3 版本。现在,事不宜迟,让我们开始吧!

文件系统API

访问文件系统、管理和编辑文件可能是服务器端最重要的任务之一。因此,Node.js 被认为提供了这样的功能。它以文件系统 (FS) API 的形式实现,包含大量的方法和属性。虽然此 API 的日常使用通常仅限于读写文件,但还有更多值得探索的地方……

异步特性

对文件执行的操作可能需要一段时间。由于 JS 的单线程特性,FS API 以异步的方式提供了解决这个问题的方案,这显而易见。因此,所有与读写相关的方法都有异步和同步版本。由于异步无疑是此类情况下的更佳解决方案,因此同步版本的方法通常带有-Sync后缀。需要注意的是,我们强烈不建议使用同步方法,因为使用同步方法会阻塞主线程执行任何其他操作。请务必谨慎使用(除非万不得已)!

出于上述原因,我们将仅关注 API 的异步方法。它们的同步方法看起来非常相似(除了回调和返回值),如果您想了解更多信息,可以随时查看官方文档。

阅读

访问检查

读取文件的过程,或者说访问文件的过程,是所有文件系统相关过程中相对最简单的。但是,在读取文件本身之前,最好先使用方法检查一下文件是否可用fs.access()

const fs = require("fs");

fs.access("file.js", fs.constants.F_OK, err => {
    console.log(err ? "Doesn't exist" : "Exists");
});
Enter fullscreen mode Exit fullscreen mode

与许多其他 FS 方法一样,fs.access()文件路径作为第一个参数。传递此参数时,请记住它几乎总是有3 种可接受的形式-字符串缓冲区URL 对象

const pathStr = "file.js";
const pathBuff = Buffer.from("file.js");
const pathURL = new URL("file:///current/dir/file.js");
Enter fullscreen mode Exit fullscreen mode

字符串和 Buffer 形式可以表示相对路径和绝对路径,而URL仅限于使用file: 协议绝对路径。表示路径的数据类型取决于您的用例,默认很可能是字符串形式。此外,Windows 系统处理绝对路径和驱动器号的方式存在一些问题——更多信息请参阅文档

第二个可选参数通常称为模式 (mode),用于定义您需要对给定文件赋予何种类型的访问权限。例如,可以是读、写权限,或者只是简单地检查文件是否存在。它用一个整数表示,因此,fs.access()考虑到方法,您通常会使用文件访问常量 (File Access Constants)fs.constants设置它。这些常量分别是F_OKR_OKW_OK和 ,X_OK分别表示文件可见性(如果存在)、读权限、写权限和执行权限。

最后,你需要传递一个回调函数,如果出现错误,该回调函数会返回错误信息,否则不返回任何信息。这样,如果没有错误抛出,你就可以确保你拥有对文件的正确访问权限。

读取文件

访问检查结果正确后,您可以继续读取文件。在 Node.js 中,这并不比调用更难fs.readFile()。作为参数,您必须传递文件路径和回调函数,以便以缓冲区格式访问文件数据。

// ...
fs.readFile("file.js", (err, data) => {
    if (!err) {
        console.log(data); // <Buffer ...>
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

但是,缓冲区格式的数据实际上没什么用。当然,您仍然可以按自己的方式使用它,例如稍后解析它,但假设我们想要以“文本”格式访问文件内容,也就是使用标准utf8 编码。为此,我们可以利用可选的options 参数,并传递一个指示编码的字符串或一个具有encodingflag属性的对象。第二个参数应该是一个由可用的文件系统标志**组成的字符串,例如"a"(append)、"r"(read、default) 或"w"(write)。

// ...
fs.readFile("file.js", "utf8", (err, data) => {
    if (!err) {
        console.log(data); // file content
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

读取目录

不建议使用fs.readFile()目录路径,因为它的行为与平台相关(主要是抛出错误)。您应该使用相应的fs.readdir()方法。从形式上看,此方法与文件读取方法极其相似——参数相同,只是可选参数不同,并且方法名称中的字母为小写。

// ...
fs.readdir("some/dir", (err, entries) => {
    if (!err) {
        console.log(entries); // ["file1.js", "file2.js"]
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

在选项对象中,编码默认为"utf8"现在("buffer"如果需要缓冲区则设置为),其次,withFileTypes布尔值设置为true,会生成一个fs.Dirent实例数组,并通过诸如、或等方法提供有用.isDirectory().isFile()信息.isSymbolicLink()

// ...
fs.readdir("some/dir", {withFileTypes: true }, (err, entries) => {
    if (!err) {
        entries.forEach(entry => {
            console.log(entry.isFile()); // true
        });
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

链接

说到链接,你可以使用轻松获取其源路径fs.readlink()。其形式与前面的方法类似,可选的对象属性仅包含编码,默认为"utf8"

// ...
fs.readlink("symlinkedFile.js", (err, link) => {
    if (!err) {
        console.log(link); // symlink source path 
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

文件描述符

最后但同样重要的是,我们有fs.open()。它是一个底层方法,几乎​​所有与文件系统读写相关的 Node.js 方法都在内部使用。给定路径、系统标志字符串、可选的模式编号和回调函数,它可以根据传递的参数创建、读取或重新创建文件,该文件稍后将可用于读取、写入或其他操作。需要注意的是,与 相比,此方法的模式参数也可以使用( File Open Constantsfs.access() )进行设置,但这次它们以 开头例如fs.constantsO_O_RDONLYO_WRONLY

// ...
fs.open("file.js", "r+", fs.constants.O_RDWR, (err, fd) => {
    if (!err) {
        console.log(fd);
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

同样,这是一个更底层的方法,你很可能不会在日常任务中使用它。这里,最重要的事情之一是它返回的值——通常名为fd。它就是所谓的文件描述符。它基本上是给定文件的整数 ID。它经常在 FS 模块文档中被引用,并被其他底层方法使用,例如fs.read()fs.write()与缓冲区更深入地交互。同样,我们不会介绍它们,因为你在大多数 FS 任务中并不需要它们。但是,更有趣的是,文件描述符也可以用于某些 FS 方法的路径,例如fs.readFile()

// ...
fs.open("file.js", "r+", fs.constants.O_RDWR, (err, fd) => {
    if (!err) {
        fs.readFile(fd, "utf8", (err, data) => {
            if (!err) {
                console.log(data);
            }
        });
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

文件“打开”后fs.open()可以稍后通过极其简单的方式“关闭”,fs.close()仅需文件描述符和回调即可。

// ...
fs.close(fd, () => {
    if (!err) {
        // ...
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

如您所见,读取文件非常简单。您只需要了解一些有关这些内容fs.constants和文件系统标志的知识。但即使如此,这只适用于更高级的使用,支持 TS 的现代 IDE 或具有自动完成功能的代码编辑器很可能会为您记住它们。此外,不要让上面的例子蒙蔽了您的双眼——处理 FS 错误需要比简单的 if 检查更加小心。最后,如果您想知道为什么只有 是用驼峰fs.readFile()命名的(除了-Sync对应项),那是因为它们代表了。用驼峰命名的方法是由 Node.js 本身实现的,而其他方法是仿照POSIX C 函数建模的。所有即将出现的方法都是如此。注意单词的方法!

写作

在文件系统 (FS) 相关的操作中,写入操作可以理解为两种方式:要么是将内容写入文件,要么是对文件系统进行任何类型的更改(包括修改文件)。在这里,我们采用第二种更广泛的理解方式。

写入文件

从简单写入文件内容开始,我们先介绍fs.writeFile()方法。这里,我们提供了可写文件(或文件描述符)的路径、以字符串或缓冲区形式写入的数据"w"以及回调函数。附加选项对象可以包含标志(默认为文件系统标志字符串)、您提供的数据的编码(默认为"utf8")和模式属性,或者是一个仅指定编码的简单字符串。但是,大多数情况下,没有它们您也能正常工作。

// ...
fs.writeFile("file.js", "Data to be written", err => {
    if (!err) {
        console.log("Written");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

虽然它会fs.writeFile()完全清除文件之前的内容,fs.appendFile()但当你想在文件中添加内容时,它也能很好地完成这项工作。它的调用结构与上面的几乎相同fs.writeFile(),唯一的区别是可选的文件系统标志字符串(文件属性)默认"a"允许附加操作。

// ...
fs.appendFile("file.js", "Data to be appended", err => {
    if (!err) {
        console.log("Appended");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

最后,你还可以使用截断给定文件的当前内容fs.truncate()。它只需要一个文件路径和一个数字,表示你想要截断到多长。哦,对了,肯定还有回调。

// ...
fs.truncate("file.js", 10, err => {
    if (!err) {
        console.log("Truncated");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

如果提供的长度超出了给定文件的长度,它将被空字符填充,从而在文件中留下奇怪的、很可能是不需要的字符。您不能将此方法与文件描述符一起使用。为此,您可以使用其直接对应方法,称为fs.ftruncate()

目录

Node.js 还提供了一组与更改/写入目录相关的方法。其中一种为许多终端用户所熟知的方法就是。它接受新目录的fs.mkdir()路径、选项对象(可选)和一个回调函数作为参数。在选项对象中,你可以传递 mode 属性(同样用于权限等)和一个递归布尔值,该布尔值指示如果指向路径中提供的目录的父目录不存在,是否应创建它们。

// ...
fs.mkdir("my/new/dir", {recursive: true}, err => {
    if(!err) {
        console.log("Created");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

如果您的新目录仅用于存储一些临时数据,则应使用fs.mkdtemp()方法。它与 略有不同fs.mkdir()。它不使用路径,而是使用前缀参数,该参数类似于路径,但稍后会添加六个随机字符"utf8"。Options 对象采用 encoding 属性(默认为),该属性指示处理后的路径的编码,但您也可以使用字符串格式。最后,除了标准 err 参数外,还会提供一个回调函数,其中包含新临时目录的名称。

const fs = require("fs");
const os = require("os");
const path = require("path");

fs.mkdtemp(path.join(os.tmpdir(), "mydir"), (err, tempDir) => {
  if (!err) {
    console.log(tempDir); // e.g. /tmp/mydirY4ciGj on Linux
  }
});
Enter fullscreen mode Exit fullscreen mode

只需记住遵循在操作系统的临时文件夹中创建临时目录的谨慎做法 - 它不会自动完成!

最后,您可以通过简单的调用删除指定的目录fs.rmdir()——这是标准做法。需要注意的是,删除前目录必须是空的!

// ...
fs.rmdir("dir/to/remove", err => {
    if (!err) {
        console.log("Removed");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

链接

创建硬链接和符号链接也可以被视为将更改写入文件系统的活动。在 Node.js 中,你可以使用一个不错的方法来创建符号链接fs.symlink()。该方法需要链接的目标和路径作为参数。

// ...
fs.symlink("target/to/symlink", "symlink/dir", err => {
    if (!err) {
        console.log("Symlinked");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

只有Windows才需要通过要求一个其他平台都不支持的类型参数来让事情变得更加困难。它是一个字符串,可以取值为"dir""file""junction",具体取决于符号链接目标的类型。

可以使用方法创建硬链接fs.link(),就像使用一样,fs.symlink()但这次没有 Windows 类型参数。

// ...
fs.link("target/to/link", "link/dir", err => {
    if (!err) {
        console.log("Linked");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

可以通过提供其路径来移除链接fs.unlink()。此方法仅适用于文件链接。对于目录,请使用前面提到的fs.rmdir()

// ...
fs.unlink("link/dir", err => {
    if (!err) {
        console.log("Unlinked");
    }
});
// ...
Enter fullscreen mode Exit fullscreen mode

其他变化

除了上述所有优点之外,在 Node.js 中你还可以重命名或复制文件。第一个操作可以通过fs.rename()方法执行,只需要传入当前路径和新路径……当然还有一个回调。

// ...
fs.rename("file.js", "renamedFile.js", err => {
  if (!err) {
    console.log("Renamed");
  }
});
// ...
Enter fullscreen mode Exit fullscreen mode

复制文件的操作稍微复杂一些,需要您使用fs.copyFile()方法并传递源路径和目标路径,以及一些标志(可选)。这些标志可以通过fs.constants文件复制常量)中的常量进行设置 - COPYFILE_EXCLCOPYFILE_FICLONE和 ,COPYFILE_FICLONE_FORCE它们都与源路径和目标路径之间的关系有关。

// ...
fs.copyFile("file.js", "dest.js", err => {
  if (!err) {
      console.log("Copied");
  }
});
// ...
Enter fullscreen mode Exit fullscreen mode

暂停

就这些了吗?嗯……当然不是!还有很多内容要讲,包括所有其他方法,甚至更多 Node.js 的精华!光是写一篇,甚至阅读(恕我直言)这么长的文章,肯定不是什么愉快的经历。所以,请记住,我们还没有结束,我们的探索将在本系列的后续文章中继续。

那么,你喜欢这篇文章吗?它今天有没有帮助你学到新东西?如果是,请与他人分享!另外,请在评论区留言我知道你的想法。如果你想及时了解最新内容(包括本系列和后续文章),请务必查看我的个人博客,并在TwitterFacebook上关注我 。一如既往,感谢你阅读这篇文章,祝你拥有美好的一天!

鏂囩珷鏉ユ簮锛�https://dev.to/areknawo/node-js-file-system-api-beginner-friend-guide-b6l
PREV
解决问题的艺术 概述 实现结果 学习解决问题 开放式结局 片尾字幕 资源
NEXT
完整的 Monorepo 设置教程 你说 Monorepo?那么,它值得吗?如何搭建 Monorepo?Lerna 太棒了!Monorepos……😵