【Node】node的fs模块介绍及使用(一)

文章目录

  • 简言
  • [File system](#File system)
    • [Promise example 承诺示例](#Promise example 承诺示例)
    • [Callback example 回调示例](#Callback example 回调示例)
    • [Synchronous example 同步示例](#Synchronous example 同步示例)
    • [Promises API 承诺API](#Promises API 承诺API)
      • [Class: FileHandle](#Class: FileHandle)
        • [Event: 'close' 关闭文件](#Event: 'close' 关闭文件)
        • [filehandle.appendFile(data[, options]) 添加数据](#filehandle.appendFile(data[, options]) 添加数据)
        • [filehandle.chmod(mode) 修改权限](#filehandle.chmod(mode) 修改权限)
        • [filehandle.chown(uid, gid) 修改文件所有权](#filehandle.chown(uid, gid) 修改文件所有权)
        • [filehandle.close() 关闭文件句柄](#filehandle.close() 关闭文件句柄)
        • [filehandle.createReadStream([options]) 创建阅读流](#filehandle.createReadStream([options]) 创建阅读流)
        • [filehandle.createWriteStream([options]) 创建写入流](#filehandle.createWriteStream([options]) 创建写入流)
        • filehandle.datasync()
        • filehandle.fd
        • [filehandle.read(buffer, offset, length, position) 读取数据](#filehandle.read(buffer, offset, length, position) 读取数据)
        • filehandle.read([options])
        • [filehandle.read(buffer[, options])](#filehandle.read(buffer[, options]))
        • [filehandle.readableWebStream([options]) 获取读取流](#filehandle.readableWebStream([options]) 获取读取流)
        • [filehandle.readFile(options) 读取文件内容](#filehandle.readFile(options) 读取文件内容)
        • [filehandle.readLines([options]) 按行读取](#filehandle.readLines([options]) 按行读取)
        • [filehandle.readv(buffers[, position])](#filehandle.readv(buffers[, position]))
        • filehandle.stat([options])
        • [filehandle.sync() 数据刷新](#filehandle.sync() 数据刷新)
        • [filehandle.truncate(len) 文件数据截取](#filehandle.truncate(len) 文件数据截取)
        • [filehandle.utimes(atime, mtime)](#filehandle.utimes(atime, mtime))
        • [filehandle.write(buffer, offset[, length[, position]]) buffer数据添加](#filehandle.write(buffer, offset[, length[, position]]) buffer数据添加)
        • [filehandle.write(buffer[, options])](#filehandle.write(buffer[, options]))
        • [filehandle.write(string[, position[, encoding]]) 字符串数据添加](#filehandle.write(string[, position[, encoding]]) 字符串数据添加)
        • [filehandle.writeFile(data, options) 数据写入到文件](#filehandle.writeFile(data, options) 数据写入到文件)
        • [filehandle.writev(buffers[, position]) buffer数据数组写入](#filehandle.writev(buffers[, position]) buffer数据数组写入)
      • [fsPromises.access(path[, mode])](#fsPromises.access(path[, mode]))
      • [fsPromises.appendFile(path, data[, options]) 向文件追加数据](#fsPromises.appendFile(path, data[, options]) 向文件追加数据)
      • [fsPromises.chmod(path, mode) 更改文件权限](#fsPromises.chmod(path, mode) 更改文件权限)
      • [fsPromises.chown(path, uid, gid)更改文件的所有权](#fsPromises.chown(path, uid, gid)更改文件的所有权)
      • [fsPromises.copyFile(src, dest[, mode]) 复制文件](#fsPromises.copyFile(src, dest[, mode]) 复制文件)
      • [fsPromises.lchmod(path, mode)](#fsPromises.lchmod(path, mode))
      • [fsPromises.lchown(path, uid, gid)](#fsPromises.lchown(path, uid, gid))
      • [fsPromises.lutimes(path, atime, mtime)](#fsPromises.lutimes(path, atime, mtime))
      • [fsPromises.link(existingPath, newPath) 创建链接](#fsPromises.link(existingPath, newPath) 创建链接)
      • [fsPromises.lstat(path[, options])](#fsPromises.lstat(path[, options]))
      • [fsPromises.mkdir(path[, options]) 异步创建目录](#fsPromises.mkdir(path[, options]) 异步创建目录)
      • [fsPromises.mkdtemp(prefix[, options]) 创建临时目录](#fsPromises.mkdtemp(prefix[, options]) 创建临时目录)
      • [fsPromises.open(path, flags[, mode]) 打开文件](#fsPromises.open(path, flags[, mode]) 打开文件)
      • [fsPromises.opendir(path[, options]) 打开文件目录](#fsPromises.opendir(path[, options]) 打开文件目录)
      • [fsPromises.readdir(path[, options]) 读取目录内容](#fsPromises.readdir(path[, options]) 读取目录内容)
      • [fsPromises.readFile(path[, options]) 读取文件](#fsPromises.readFile(path[, options]) 读取文件)
      • [fsPromises.readlink(path[, options]) 读取链接内容](#fsPromises.readlink(path[, options]) 读取链接内容)
      • [fsPromises.realpath(path[, options])](#fsPromises.realpath(path[, options]))
      • [fsPromises.rename(oldPath, newPath) 移动](#fsPromises.rename(oldPath, newPath) 移动)
      • [fsPromises.rmdir(path[, options]) 删除目录](#fsPromises.rmdir(path[, options]) 删除目录)
      • [fsPromises.rm(path[, options]) 删除文件和目录](#fsPromises.rm(path[, options]) 删除文件和目录)
      • [fsPromises.stat(path[, options]) 返回文件信息](#fsPromises.stat(path[, options]) 返回文件信息)
      • [fsPromises.statfs(path[, options]) 返回已挂载文件系统的相关信息。](#fsPromises.statfs(path[, options]) 返回已挂载文件系统的相关信息。)
      • [fsPromises.symlink(target, path[, type]) 创建符号链接](#fsPromises.symlink(target, path[, type]) 创建符号链接)
      • [fsPromises.truncate(path[, len]) 截取内容](#fsPromises.truncate(path[, len]) 截取内容)
      • [fsPromises.unlink(path) 删除链接或文件](#fsPromises.unlink(path) 删除链接或文件)
      • [fsPromises.utimes(path, atime, mtime) 修改文件时间](#fsPromises.utimes(path, atime, mtime) 修改文件时间)
      • [fsPromises.watch(filename[, options]) 监听文件](#fsPromises.watch(filename[, options]) 监听文件)
      • [fsPromises.writeFile(file, data[, options]) 数据写入](#fsPromises.writeFile(file, data[, options]) 数据写入)
      • fsPromises.constants
  • 结语

简言

通过 node:fs 模块,可以以标准 POSIX 函数为模型与文件系统进行交互。

File system

通过 node:fs 模块,可以以标准 POSIX 函数为模型与文件系统进行交互。

要使用基于承诺的应用程序接口:

javascript 复制代码
import * as fs from 'node:fs/promises';

使用回调和同步 API:

javascript 复制代码
import * as fs from 'node:fs';

所有文件系统操作都有同步、回调和基于承诺的形式,并可使用 CommonJS 语法和 ES6 模块 (ESM) 访问。

Promise example 承诺示例

基于承诺的操作会返回一个承诺,该承诺会在异步操作完成时兑现。

javascript 复制代码
import { unlink } from 'node:fs/promises';

try {
  await unlink('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (error) {
  console.error('there was an error:', error.message);
}

Callback example 回调示例

回调形式将完成回调函数作为最后一个参数,并异步调用操作。传递给完成回调函数的参数取决于方法,但第一个参数总是为异常保留。如果操作成功完成,则第一个参数为空或undefined(未定义)。

javascript 复制代码
import { unlink } from 'node:fs';

unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('successfully deleted /tmp/hello');
});

在需要最高性能(包括执行时间和内存分配)时,基于回调的 node:fs 模块 API 版本比使用 promise API 更为可取。

Synchronous example 同步示例

同步 API 会阻止 Node.js 事件循环和 JavaScript 的进一步执行,直到操作完成。异常会立即抛出,可以使用 try...catch 进行处理,也可以让异常冒泡。

javascript 复制代码
import { unlinkSync } from 'node:fs';

try {
  unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

Promises API 承诺API

fs/promises API 提供返回承诺的异步文件系统方法。

promise API 使用底层 Node.js 线程池在事件循环线程之外执行文件系统操作。这些操作不是同步或线程安全的。在对同一文件执行多个并发修改时必须小心谨慎,否则可能会导致数据损坏。

Class: FileHandle

<FileHandle> 对象是数字文件描述符的对象包装器。

<FileHandle> 对象的实例由 fsPromises.open() 方法创建。

所有 <FileHandle> 对象都是 <EventEmitter>s 。

如果未使用 filehandle.close() 方法关闭 <FileHandle> 文件,系统将尝试自动关闭文件描述符并发出进程警告,以帮助防止内存泄漏。请不要依赖这种行为,因为它可能不可靠,文件可能无法关闭。相反,请始终显式关闭 <FileHandle>s 文件。Node.js 今后可能会更改此行为。

Event: 'close' 关闭文件

当 <FileHandle> 已关闭且不能再使用时,"close "事件就会被触发。

filehandle.appendFile(data[, options]) 添加数据

参数:

  • data ------ <string> | <Buffer> | <TypedArray> | <DataView> | <AsyncIterable> | <Iterable> | <Stream>
  • options ------ 配置对象
    • encoding ------ 默认值:'utf8'
    • flush ------ 如果为 "true",底层文件描述符将在关闭前被刷新。默认值:false。
  • 返回值 成功后返回undefined。
    filehandle.writeFile() 的别名。
    在对文件句柄进行操作时,模式不能从 fsPromises.open() 设置的模式进行更改。因此,这等同于 filehandle.writeFile()。
filehandle.chmod(mode) 修改权限

mode------ 文件模式位掩码。

修改文件的权限。

权限可以用以下几种方式来表示:

  • 数值:如0o777 (所有用户都有读、写和执行权限)

  • 字符串:如'777' (同上)

  • 或者使用符号:如u+x (给文件所有者添加执行权限)

更多详细信息请参考linux的文件修改权限命令。

filehandle.chown(uid, gid) 修改文件所有权
  • uid ------ 文件新所有者的用户 ID。
  • gid ------ 文件新组的组 ID。
    更改文件的所有权。
filehandle.close() 关闭文件句柄

在等待句柄上的任何待处理操作完成后,关闭文件句柄。

javascript 复制代码
import { open } from "node:fs/promises";

let filehandle;
try {
  filehandle = await open("thefile.txt", "r");
  console.log(filehandle.readFile());
} catch (error) {
} finally {
  if (filehandle) {
    await filehandle.close();
  }
}
filehandle.createReadStream([options]) 创建阅读流

参数:

  • options ------ 配置对象
    • encoding ------ 默认值:空。
    • autoClose ------ 是否自动关闭 默认值:true。
    • emitClose ------ 关闭后是否发出关闭事件 默认值:true。
    • start ------ 开始索引
    • end ------ 结束索引
    • highWaterMark ------ 默认值:64 * 1024

与 <stream.Readable> 的 16 KiB 默认 highWaterMark 不同,此方法返回的流的默认 highWaterMark 为 64 KiB。

选项可以包含开始和结束值,以便从文件中读取一定范围的字节,而不是整个文件。start 和 end 都是包容性的,从 0 开始计数,允许的值范围是 [0,Number.MAX_SAFE_INTEGER]。如果省略 start 或未定义 start,filehandle.createReadStream() 将从当前文件位置开始顺序读取。编码可以是 接受的任何一种编码。

如果 FileHandle 指向只支持阻塞读取的字符设备(如键盘或声卡),则读取操作在数据可用前不会结束。这会导致进程无法退出,数据流无法自然关闭。

默认情况下,数据流销毁后会发出 "关闭 "事件。将 emitClose 选项设为 false 可以改变这种行为。

如果 autoClose 为 false,那么即使出现错误,文件描述符也不会被关闭。关闭文件描述符并确保没有文件描述符泄漏是应用程序的责任。如果将 autoClose 设为 true(默认行为),在出现 "错误 "或 "结束 "时,文件描述符将自动关闭。

示例:读取 100 字节文件的最后 10 字节:

javascript 复制代码
import { open } from 'node:fs/promises';

const fd = await open('sample.txt');
fd.createReadStream({ start: 90, end: 99 }); 
filehandle.createWriteStream([options]) 创建写入流

参数:

  • options ------ 配置对象
    • encoding ------ 默认值:空。
    • autoClose ------ 是否自动关闭 默认值:true。
    • emitClose ------ 关闭后是否发出关闭事件 默认值:true。
    • start ------ 开始索引
    • highWaterMark ------ 默认值:64 * 1024
    • flush ------ 如果为 "true",底层文件描述符将在关闭前被刷新。默认值:false。

选项还可以包括一个起始选项,允许在文件开始后的某个位置写入数据,允许的值范围是[0, Number.MAX_SAFE_INTEGER]。修改文件而不是替换文件,可能需要将 flags open 选项设置为 r+ 而不是默认的 r。

如果将 autoClose 设为 true(默认行为),那么在 "出错 "或 "完成 "时,文件描述符将自动关闭。如果 autoClose 为 false,那么即使出现错误,文件描述符也不会关闭。关闭文件描述符并确保没有文件描述符泄漏是应用程序的责任

默认情况下,数据流销毁后会发出 "关闭 "事件。将 emitClose 选项设为 false 可以改变这种行为。

filehandle.datasync()

强制与文件相关的所有当前排队 I/O 操作进入操作系统的同步 I/O 完成状态。

详情请参考 POSIX fdatasync(2) 文档。

与 filehandle.sync 不同,该方法不会刷新已修改的元数据。

filehandle.fd

由 <FileHandle> 对象管理的数字文件描述符。

filehandle.read(buffer, offset, length, position) 读取数据

参数:

  • buffer <Buffer> | <TypedArray> | <DataView> 将读取的文件数据填入的缓冲区。
  • offset <整数> 缓冲区中开始填充数据的位置。默认值:0
  • length <整数> 要读取的字节数。默认值:buffer.byteLength - 偏移量
  • position <integer> | <bigint> | <null> 从文件开始读取数据的位置。如果为空或-1,将从当前文件位置读取数据,并更新位置。如果 position 为非负整数,当前文件位置将保持不变。默认值::空
    -返回值,使用具有两个属性的对象成功后执行:
    • bytesRead --- 读取的字节数
    • buffer ------ 传递的缓冲区参数的引用。

从文件中读取数据并将其存储在给定的缓冲区中。

如果文件没有被同时修改,当读取的字节数为零时,文件结束。

javascript 复制代码
import { open } from "node:fs/promises";

let filehandle;
try {
  filehandle = await open("./src/file/thefile.txt", "r");
  const { bytesRead, buffer } = await filehandle.read();
  console.log(bytesRead, buffer.toString());
} catch (error) {
  console.log(error);
} finally {
  if (filehandle) {
    await filehandle.close();
  }
}
filehandle.read([options])

从文件中读取数据并将其存储在给定的缓冲区中。

如果文件没有被同时修改,当读取的字节数为零时,文件结束。

filehandle.read(buffer[, options])

从文件中读取数据并将其存储在给定的缓冲区中。

如果文件没有被同时修改,当读取的字节数为零时,文件结束。

filehandle.readableWebStream([options]) 获取读取流

返回可用于读取文件数据的 ReadableStream。

如果此方法被调用多次,或在 FileHandle 关闭或关闭后被调用,则会产生错误。

javascript 复制代码
import {
  open,
} from 'node:fs/promises';

const file = await open('./some/file/to/read');

for await (const chunk of file.readableWebStream())
  console.log(chunk);

await file.close();

虽然 ReadableStream 会读完文件,但不会自动关闭 FileHandle。用户代码仍必须调用 fileHandle.close() 方法。

filehandle.readFile(options) 读取文件内容

异步读取文件的全部内容。

如果选项是字符串,则指定编码。

<FileHandle> 必须支持读取。

如果在文件句柄上调用了一个或多个 filehandle.read(),然后又调用了 filehandle.readFile(),那么数据将从当前位置读取,直到文件结束。它并不总是从文件开头读取数据。

javascript 复制代码
try {
  filehandle = await open("./src/file/thefile.txt", "r");
  const buff = await filehandle.readFile();
  console.log(buff.toString());
  filehandle.close();
  filehandle = await open("./src/file/thefile.txt", "r");

  let res = await filehandle.readFile({ encoding: "utf8" });
  console.log(res.toString());
} catch (error) {
  console.log(error);
} finally {
  if (filehandle) {
    await filehandle.close();
  }
}
filehandle.readLines([options]) 按行读取

参数:

  • oprions<对象
    • encoding <string> 默认值:null
    • autoClose <boolean> 默认值:true
    • emitClose <布尔> 默认值: true
    • start <整数
    • end <整数> 默认值:Infinity
    • highWaterMark <整数> 默认值:64 * 1024

在文件上创建读取线接口和流的方便方法。有关选项,请参阅 filehandle.createReadStream() 。

javascript 复制代码
import { open } from 'node:fs/promises';

const file = await open('./some/file/to/read');

for await (const line of file.readLines()) {
  console.log(line);
}
filehandle.readv(buffers[, position])

参数:

  • buffers ------ buffer 数组
  • position ------ 从文件开头读取数据的偏移量。如果 position 不是数字,数据将从当前位置读取。默认值:空
  • 返回值 ------ 成功后执行一个包含两个属性的对象:
    • bytesRead ------ 读取的字节数。
    • buffers ------ 属性,该属性包含对缓冲区输入的引用。
      从文件读取并写入 <ArrayBufferView> 数组
filehandle.stat([options])

选项 <对象

bigint <boolean>返回的 <fs.Stats> 对象中的数值是否应为 bigint。默认值:false。

返回值:<Promise> 使用文件的 <fs.Stats> 实现。

filehandle.sync() 数据刷新

请求将打开的文件描述符的所有数据刷新到存储设备。具体实现取决于操作系统和设备。详情请参考 POSIX fsync(2) 文档。

filehandle.truncate(len) 文件数据截取

截断文件。

如果文件大于 len 字节,文件中将只保留前 len 字节。

下面的示例只保留了文件的前四个字节:

javascript 复制代码
import { open } from 'node:fs/promises';

let filehandle = null;
try {
  filehandle = await open('temp.txt', 'r+');
  await filehandle.truncate(4);
} finally {
  await filehandle?.close();
} 

如果文件先前短于 len 字节,则文件将被扩展,扩展部分将填充空字节('\0'):

如果 len 为负数,则使用 0。

filehandle.utimes(atime, mtime)

更改 <FileHandle> 引用对象的文件系统时间戳,然后在成功后履行承诺,不含任何参数。

filehandle.write(buffer, offset[, length[, position]]) buffer数据添加

参数:

  • 缓冲区 <Buffer> | <TypedArray> | <DataView>
  • offset <整数> 要写入的数据在缓冲区中的起始位置。
  • length <整数> 缓冲区中要写入的字节数。默认值:buffer.byteLength - 偏移量
  • position <integer> | <null> 从文件开头写入缓冲区数据的偏移量。如果 position 不是数字,数据将写入当前位置。更多详情,请参阅 POSIX pwrite(2) 文档。默认值:空
  • 返回值<承诺
    将缓冲区写入文件。
    承诺通过一个包含两个属性的对象来实现:
    bytesWritten <整数> 写入的字节数。
    buffer <Buffer> | <TypedArray> | <DataView> 对写入的缓冲区的引用。
    在同一文件上多次使用 filehandle.write() 而不等待承诺实现(或拒绝)是不安全的。在这种情况下,请使用 filehandle.createWriteStream()。
    在 Linux 上,以追加模式打开文件时,位置写入不起作用。内核会忽略位置参数,并始终将数据追加到文件末尾。
filehandle.write(buffer[, options])

将缓冲区写入文件。

与上面的 filehandle.write 函数类似,该版本需要一个可选的选项对象。如果没有指定选项对象,则默认使用上述值。

filehandle.write(string[, position[, encoding]]) 字符串数据添加

将字符串写入文件。如果字符串不是字符串,承诺将被拒绝,并显示错误。

承诺通过一个包含两个属性的对象来实现:

  • bytesWritten <整数> 写入的字节数
  • buffer <string> 写入字符串的引用。
    在同一文件上多次使用 filehandle.write() 而不等待承诺实现(或拒绝)是不安全的。在这种情况下,请使用 filehandle.createWriteStream()。
    在 Linux 上,以追加模式打开文件时,位置写入不起作用。内核会忽略位置参数,并始终将数据追加到文件末尾。
filehandle.writeFile(data, options) 数据写入到文件

数据可以是字符串、缓冲区、 或 对象。成功后,将履行承诺,不带参数。

如果选项是字符串,则指定编码。

<FileHandle> 必须支持写入。

在同一文件上多次使用 filehandle.writeFile() 而不等待承诺实现(或拒绝)是不安全的。

如果在一个文件句柄上调用了一次或多次 filehandle.write(),然后又调用了一次 filehandle.writeFile(),数据将从当前位置写入,直到文件结束。它并不总是从文件开头写起。

javascript 复制代码
try {
  filehandle = await open("./src/file/thefile.txt", "r");
  const buff = await filehandle.readFile();
  console.log(buff.toString());
  filehandle.close();
  filehandle = await open("./src/file/thefile.txt", "r+");

  await filehandle.truncate(0);
  filehandle.write("你好");
  filehandle.writeFile("\nHHH");
  filehandle.sync();
} catch (error) {
  console.log(error);
} finally {
  if (filehandle) {
    await filehandle.close();
  }
}
filehandle.writev(buffers[, position]) buffer数据数组写入

将 <ArrayBufferView>s 数组写入文件。

在同一文件上多次调用 writev() 而不等待承诺实现(或拒绝)是不安全的。

在 Linux 上,当文件以追加模式打开时,位置写入不起作用。内核会忽略位置参数,并始终将数据追加到文件末尾。

fsPromises.access(path[, mode])

测试用户对 path 指定的文件或目录的权限。模式参数是一个可选整数,用于指定要执行的可访问性检查。模式应为 fs.constants.F_OK,或由 fs.constants.R_OK、fs.constants.W_OK 和 fs.constants.X_OK 中任意一个的 bitwise OR 组成的掩码(例如 fs.constants.W_OK | fs.constants.R_OK)。请查看文件访问常量,了解模式的可能值。

如果无障碍检查成功,则履行承诺,但不产生任何值。如果任何可访问性检查失败,则会以 <Error> 对象拒绝该承诺。下面的示例检查当前进程是否可以读写 /etc/passwd 文件。

javascript 复制代码
import { access, constants } from 'node:fs/promises';

try {
  await access('/etc/passwd', constants.R_OK | constants.W_OK);
  console.log('can access');
} catch {
  console.error('cannot access');
} 

不建议在调用 fsPromises.open() 之前使用 fsPromises.access() 检查文件的可访问性。这样做会引入竞赛条件,因为其他进程可能会在两次调用之间改变文件的状态。相反,用户代码应直接打开/读取/写入文件,并处理文件不可访问时出现的错误。

fsPromises.appendFile(path, data[, options]) 向文件追加数据

参数:

  • path ------ 文件路径
  • data ------ 数据
  • options ------ 配置对象
    • encoding ------ 编码,默认值:'utf8'
    • mode ------ 文件权限,默认0o666
    • flag ------ 操作类型标志。默认'a',即打开文件进行添加。如果文件不存在,则将创建该文件。
    • flush ------ 如果为 "true",底层文件描述符将在关闭前被刷新。默认值:false。

异步向文件追加数据,如果文件不存在,则创建文件。

如果选项是字符串,则指定编码。

模式(mode)选项只影响新创建的文件。详情请参阅 fs.open()。

路径可指定为已打开用于添加的 <FileHandle> 文件(使用 fsPromises.open())。

typescript 复制代码
import { appendFile } from "node:fs/promises";
appendFile("./src/file/thefile.txt", "\n我是appendFile添加的。");

fsPromises.chmod(path, mode) 更改文件权限

更改文件权限。

fsPromises.chown(path, uid, gid)更改文件的所有权

更改文件的所有权。

fsPromises.copyFile(src, dest[, mode]) 复制文件

参数:

  • src ------ 要复制的源文件名。
  • dest ------ 复制操作的目标文件名。
  • mode ------ 指定复制操作行为的可选修饰符。可以创建一个由两个或两个以上值的 bitwise OR 组成的掩码(例如,fs.constants.COPYFILE_EXCL |fs.constants.COPYFILE_FICLONE) 默认值:0。
    • fs.constants.COPYFILE_EXCL:如果 dest 已经存在,复制操作将失败。
    • fs.constants.COPYFILE_FICLONE:复制操作将尝试创建写入时复制重链接。如果平台不支持写入时复制,则会使用后备复制机制。
    • fs.constants.COPYFILE_FICLONE_FORCE:复制操作将尝试创建写时复制重链接。如果平台不支持写入时复制,则操作将失败。

异步复制 src 到 dest。默认情况下,如果 dest 已存在,则会被覆盖。

不保证复制操作的原子性。如果在目标文件打开供写入后发生错误,系统将尝试删除目标文件。

typescript 复制代码
import { copyFile, constants } from 'node:fs/promises';

try {
  await copyFile('source.txt', 'destination.txt');
  console.log('source.txt was copied to destination.txt');
} catch {
  console.error('The file could not be copied');
}

// By using COPYFILE_EXCL, the operation will fail if destination.txt exists.
//	使用 COPYFILE_EXCL,如果 destination.txt 存在,操作将失败。
try {
  await copyFile('source.txt', 'destination.txt', constants.COPYFILE_EXCL);
  console.log('source.txt was copied to destination.txt');
} catch {
  console.error('The file could not be copied');
} 

fsPromises.lchmod(path, mode)

更改符号链接的权限。

此方法仅在 macOS 上实现。

fsPromises.lchown(path, uid, gid)

更改符号链接的所有权。

fsPromises.lutimes(path, atime, mtime)

更改文件的访问和修改时间的方法与 fsPromises.utimes() 相同,不同之处在于,如果路径指向符号链接,则不会取消引用链接:而是更改符号链接本身的时间戳。

fsPromises.link(existingPath, newPath) 创建链接

创建从 existingPath 到 newPath 的新链接。详情请查看 POSIX link(2) 文档。

fsPromises.lstat(path[, options])

等同于 fsPromises.stat(),除非 path 指向符号链接,在这种情况下,链接本身会被统计,而不是它指向的文件。详情请参考 POSIX lstat(2) 文档。

fsPromises.mkdir(path[, options]) 异步创建目录

异步创建目录。

参数:

  • path ------ 路径
  • options ------ 配置选项。
    • recursive ------ 是否递归 默认值:false
    • mode ------ 文件权限,Windows 不支持。默认值:0o777。
  • 返回值------成功后,如果递归为假,则执行未定义;如果递归为真,则执行创建的第一个目录路径。

可选的选项参数可以是一个指定模式(权限和粘性位)的整数,也可以是一个带有模式属性和递归属性的对象,后者表示是否应创建父目录。当 path 是一个已存在的目录时,调用 fsPromises.mkdir() 只会在递归属性为 false 时导致拒绝。

typescript 复制代码
import { mkdir } from 'node:fs/promises';

try {
  const projectFolder = new URL('./test/project/', import.meta.url);
  const createDir = await mkdir(projectFolder, { recursive: true });

  console.log(`created ${createDir}`);
} catch (err) {
  console.error(err.message);
}

fsPromises.mkdtemp(prefix[, options]) 创建临时目录

创建一个唯一的临时目录。在所提供前缀的末尾添加六个随机字符,即可生成唯一的目录名。由于平台不一致,请避免在前缀中使用尾随 X 字符。某些平台,尤其是 BSD,可以返回超过六个随机字符,并用随机字符替换前缀中的尾随 X 字符。

参数:

  • prefix ------ 前缀
  • options ------ 配置对象
    • encoding ------ 编码, 默认utf8
  • 返回值------使用包含新创建临时目录的文件系统路径的字符串执行。

可选的选项参数可以是一个指定编码的字符串,也可以是一个带有编码属性的对象,该属性指定了要使用的字符编码。

typescript 复制代码
import { mkdtemp } from "node:fs/promises";
import { join } from "node:path";
import { tmpdir } from "node:os";

try {
  let str = await mkdtemp(join(tmpdir(), "foo-"));
  console.log("临时目录", str);
} catch (err) {
  console.error(err);
}

fsPromises.mkdtemp() 方法会将随机选择的六个字符直接追加到前缀字符串中。例如,给定目录 /tmp,如果要在 /tmp 中创建临时目录,前缀必须以特定平台的尾部路径分隔符(require('node:path').sep)结尾。

fsPromises.open(path, flags[, mode]) 打开文件

打开 <FileHandle> 文件。

参数:

  • path ------ 文件路径。
  • flags ------ 文件操作系统类型标志,默认'r',即可读。
  • mode ------ 如果创建文件,则设置文件模式(权限和粘性位)。默认值:0o666(可读可写)
    -返回:<Promise> 使用 <FileHandle> 对象执行。

详情请参考 POSIX open(2) 文档。

某些字符(< > : " / \ | ? *)在 Windows 下是保留字符,如文件命名、路径和命名空间中所述。在 NTFS 下,如果文件名包含冒号,Node.js 将打开文件系统流,如 MSDN 页面所述。

fsPromises.opendir(path[, options]) 打开文件目录

参数:

  • path <string> | <Buffer> | <URL> ------ 路径
  • options <对象
    • 编码 <string> | <null> 默认:"utf8
    • bufferSize <number> 从目录读取时内部缓冲的目录条目的数量。数值越大,性能越好,但内存占用也越高。默认值:32
    • recursive <boolean>解析后的目录将是一个包含所有子文件和目录的 。默认值:false
  • 返回:<Promise> 以 <fs.Dir> 实现。

异步打开一个目录进行迭代扫描。更多详情,请参阅 POSIX opendir(3) 文档。

创建 <fs.Dir>,其中包含读取和清理目录的所有函数。

编码选项用于设置打开目录和后续读取操作时的路径编码。

使用异步迭代的示例:

typescript 复制代码
import { opendir } from "node:fs/promises";

try {
  const dir = await opendir("./");
  for await (const dirent of dir) {
    console.log("drent::", dirent.name);
  }
} catch (err) {
  console.error(err);
}

使用异步迭代器时,<fs.Dir> 对象将在迭代器退出后自动关闭。

fsPromises.readdir(path[, options]) 读取目录内容

参数:

  • path ------ 目录路径
  • oprions ------ 配置对象。
    • encoding ------ 默认'utf8'
    • withFileTypes ------ 默认false
    • recursive ------ 为 true 时,将递归读取目录内容。在递归模式下,它会列出所有文件、子文件和目录。默认值:false。
  • 返回值 ------ 使用目录中不包含". "和"... "的文件名数组来执行。

读取目录内容。

可选的选项参数可以是一个指定编码的字符串,也可以是一个带有编码属性的对象,该属性指定了文件名使用的字符编码。如果编码设置为 "缓冲区",返回的文件名将作为 <Buffer> 对象传递。

如果 options.withFileTypes 设置为 true,返回的数组将包含 <fs.Dirent> 对象。

typescript 复制代码
try {
  const files = await readdir("./");
  for (const file of files) {
    console.log("file::", file);
  }
} catch (err) {
  console.error(err);
}

fsPromises.readFile(path[, options]) 读取文件

参数:

  • path ------ <string> | <Buffer> | <URL> | <FileHandle> 文件名或文件句柄FileHandle。
  • options ------ 配置对象。
    • encoding ------ 编码,默认null。
    • flag ------ 文件系统操作标志。默认'r',可读。
    • signal ------ 允许终止正在读取的文件
  • 返回:<Promise> 使用文件内容执行。

异步读取文件的全部内容。

如果没有指定编码(使用 options.encoding),数据将以 <Buffer> 对象的形式返回。否则,数据将是一个字符串。

如果 options 是字符串,则指定编码。

当路径为目录时,fsPromises.readFile() 的行为与特定平台有关。在 macOS、Linux 和 Windows 平台上,承诺将被拒绝并显示错误。在 FreeBSD 上,将返回目录内容的表示形式。

读取运行代码同一目录下 package.json 文件的示例:

typescript 复制代码
import { readFile } from "node:fs/promises";
try {
  const contents = await readFile("./package.json", { encoding: "utf8" });
  console.log(contents);
} catch (err) {
  console.error(err.message);
}

可以使用 <AbortSignal> 终止正在进行的 readFile。如果请求被中止,返回的承诺将被拒绝,并显示 AbortError:

typescript 复制代码
import { readFile } from 'node:fs/promises';

try {
  const controller = new AbortController();
  const { signal } = controller;
  const promise = readFile(fileName, { signal });

  // Abort the request before the promise settles.
  controller.abort();

  await promise;
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
} 

中止正在进行的请求不会中止单个操作系统请求,而是中止 fs.readFile 执行的内部缓冲。

任何指定的 <FileHandle> 必须支持读取。

fsPromises.readlink(path[, options]) 读取链接内容

参数:

  • path路径 <string> | <Buffer> | <URL>
  • options选项 <string> | <Object
    • encoding 编码 <string> 默认:"utf8
  • 返回值:<Promise>(承诺) 成功时使用 linkString 履行。
    读取 path 指向的符号链接的内容。详情请参见 POSIX readlink(2) 文档。成功后,将使用 linkString 履行承诺。
    可选的选项参数可以是一个指定编码的字符串,也可以是一个带有编码属性的对象,该属性指定了返回的链接路径要使用的字符编码。如果编码设置为 "缓冲区",返回的链接路径将作为 <Buffer> 对象传递。

fsPromises.realpath(path[, options])

使用与 fs.realpath.native() 函数相同的语义确定路径的实际位置。

只支持可转换为 UTF8 字符串的路径。

可选的选项参数可以是一个指定编码的字符串,也可以是一个带有编码属性的对象,该属性指定了路径使用的字符编码。如果编码设置为 "缓冲区",返回的路径将以 <Buffer> 对象的形式传递。

在 Linux 上,当 Node.js 与 musl libc 链接时,procfs 文件系统必须挂载在 /proc 上,此函数才能工作。Glibc 没有此限制。

fsPromises.rename(oldPath, newPath) 移动

将 oldPath 重命名为 newPath。

fsPromises.rmdir(path[, options]) 删除目录

参数:

  • path ------ 路径。
  • options ------ 配置对象.
    • maxRetries ------ 如果遇到 EBUSY、EMFILE、ENFILE、ENOTEMPTY 或 EPERM 错误,Node.js 会重试操作,每次重试的线性延迟时间为 retryDelay 毫秒。该选项表示重试次数。如果递归选项不为真,该选项将被忽略。默认值:0。
    • recursive ------ 递归,如果为 true,则执行递归目录删除。在递归模式下,操作失败时会重试。默认值:false。已废弃。
    • retryDelay ------ 两次重试之间的等待时间(毫秒)。如果递归选项不为真,该选项将被忽略。默认值:100。

删除 path 所标识的目录。

在文件(而非目录)上使用 fsPromises.rmdir(),在 Windows 下会出现 ENOENT 错误,在 POSIX 下会出现 ENOTDIR 错误,导致承诺被拒绝。

要获得与 rm -rf Unix 命令类似的行为,可使用 fsPromises.rm(),并在其中加入选项 { recursive: true, force: true }。

fsPromises.rm(path[, options]) 删除文件和目录

参数:

  • path ------ 路径。
  • options ------ 配置对象.
    • maxRetries ------ 如果遇到 EBUSY、EMFILE、ENFILE、ENOTEMPTY 或 EPERM 错误,Node.js 会重试操作,每次重试的线性延迟时间为 retryDelay 毫秒。该选项表示重试次数。如果递归选项不为真,该选项将被忽略。默认值:0。
    • recursive ------ 递归,如果为 true,则执行递归目录删除。在递归模式下,操作失败时会重试。默认值:false。已废弃。
    • retryDelay ------ 两次重试之间的等待时间(毫秒)。如果递归选项不为真,该选项将被忽略。默认值:100。
      删除文件和目录(仿效标准 POSIX rm 工具)。

fsPromises.stat(path[, options]) 返回文件信息

返回给定路径的 <fs.Stats> 对象。

fsPromises.statfs(path[, options]) 返回已挂载文件系统的相关信息。

返回给定路径的 <fs.StatFs> 对象。

fsPromises.symlink(target, path[, type]) 创建符号链接

创建符号链接。

类型参数仅用于 Windows 平台,可以是 "dir"、"file "或 "junction "之一。如果类型参数不是字符串,Node.js 将自动检测目标类型并使用 "file "或 "dir"。如果目标不存在,将使用 "file"。Windows 连接点要求目标路径是绝对路径。使用 "junction "时,目标参数将自动规范化为绝对路径。NTFS 卷上的交界点只能指向目录。

fsPromises.truncate(path[, len]) 截取内容

将路径处的内容截断(缩短或延长长度)为 len 字节。

fsPromises.unlink(path) 删除链接或文件

如果 path 指向一个符号链接,则会删除该链接,而不会影响该链接指向的文件或目录。如果 path 指向的文件路径不是符号链接,则该文件将被删除。详情请参见 POSIX unlink(2) 文档。

fsPromises.utimes(path, atime, mtime) 修改文件时间

更改 path 引用对象的文件系统时间戳。

atime 和 mtime 参数遵循这些规则:

  • 值可以是代表 Unix 纪元时间的数字、日期或数字字符串,如 "123456789.0"。
  • 如果数值无法转换为数字,或者是 NaN、Infinity 或 -Infinity,则会出错。

fsPromises.watch(filename[, options]) 监听文件

参数:

  • filename ------ 文件名或目录
  • options------ 配置对象。
    • persistent ------ 指示进程是否应在文件被监视期间继续运行。默认值:true。
    • recursive ------ 指示是监视所有子目录,还是只监视当前目录。这适用于指定目录的情况,且仅适用于支持的平台(请参阅注意事项)。默认值:false。
    • encoding ------ 指定传递给监听器的文件名所使用的字符编码。默认值:"utf8"。
    • signal ------ 一个 <AbortSignal> 用于在观察者应该停止时发出信号。
  • 返回值 ------ 带有属性的对象的 <AsyncIterator> :
    • eventType ------ 变化的类型。
    • filename ------ 已更改的文件名。
      返回一个异步迭代器,用于监视文件名的变化,其中文件名可以是文件,也可以是目录。
typescript 复制代码
const { watch } = require('node:fs/promises');

const ac = new AbortController();
const { signal } = ac;
setTimeout(() => ac.abort(), 10000);

(async () => {
  try {
    const watcher = watch(__filename, { signal });
    for await (const event of watcher)
      console.log(event);
  } catch (err) {
    if (err.name === 'AbortError')
      return;
    throw err;
  }
})(); 

在大多数平台上,每当目录中出现或消失文件名时,都会发出 "rename"。

fs.watch() 的所有注意事项也适用于 fsPromises.watch()。

fsPromises.writeFile(file, data[, options]) 数据写入

参数:

  • file <string> | <Buffer> | <URL> | <FileHandle> 文件名或 FileHandle
  • data <string> | <Buffer> | <TypedArray> | <DataView> | <AsyncIterable> | <Iterable> | <Stream>
  • 选项 <对象> | <字符串
    • encoding 编码 <string> | 默认:'utf8
    • mode 模式 <整数> 默认: 0o666
    • flag <string> 查看文件系统标志支持。默认: 'w'。
    • flush <boolean>如果所有数据已成功写入文件,且 flush 为 true,则使用 filehandle.sync() 清除数据。默认值:false。
    • signal <AbortSignal> 允许终止正在进行的写文件操作。
  • 返回:<Promise>成功时以未定义的方式实现。

数据可以是字符串、缓冲区、<AsyncIterable> 或 <Iterable> 对象。

如果数据是缓冲区,编码选项将被忽略。

如果选项是字符串,则指定编码。

模式选项只影响新创建的文件。详情请参阅 fs.open()。

任何指定的 <FileHandle> 必须支持写入。

在同一文件上多次使用 fsPromises.writeFile() 而不等待承诺结算是不安全的。

与 fsPromises.readFile 类似,fsPromises.writeFile 也是一种便捷方法,可在内部执行多次写调用,以写入传递给它的缓冲区。对于性能敏感的代码,可考虑使用 fs.createWriteStream() 或 filehandle.createWriteStream()。

可以使用 <AbortSignal> 取消 fsPromises.writeFile()。取消是 "尽力而为",可能仍有一定量的数据要写入。

typescript 复制代码
import { writeFile } from 'node:fs/promises';
import { Buffer } from 'node:buffer';

try {
  const controller = new AbortController();
  const { signal } = controller;
  const data = new Uint8Array(Buffer.from('Hello Node.js'));
  const promise = writeFile('message.txt', data, { signal });

  // Abort the request before the promise settles.
  controller.abort();

  await promise;
} catch (err) {
  // When a request is aborted - err is an AbortError
  console.error(err);
} 

中止正在进行的请求不会中止单个操作系统请求,而是中止 fs.writeFile 执行的内部缓冲。

fsPromises.constants

返回一个包含文件系统操作常用常量的对象。该对象与 fs.constants 相同。更多详情,请参阅 FS 常量。

结语

结束了。

相关推荐
羽师1 小时前
Node.js和npx关系
node.js
灵魂学者1 小时前
使用 Electron 打包项目构建 .EXE 桌面应用程序(简)
electron·node.js·vue·build·桌面应用程序
右耳朵猫AI1 小时前
Node.js技术周刊 2026年第14周
node.js
gogoing15 小时前
Node.js 模块查找策略(require 完整流程)
javascript·node.js
zhangfeng113316 小时前
小龙虾 wordbuddy 安装浏览器控制器 agent-browser npm install -g agent-browse
前端·人工智能·npm·node.js
大家的林语冰17 小时前
pnpm 11 发布,弃用 JSON 和 npm CLI,进化为纯 ES6 模块,新增 pnpm pack-app 等命令,供应链保护默认启用,要求 Node
前端·javascript·node.js
会周易的程序员18 小时前
aiDgeScanner 工业设备网络扫描与管理工具
网络·c++·物联网·架构·electron·node.js·iot
阿赛工作室19 小时前
AI时代WEB开发人员生存与发展报告
前端·人工智能·node.js
会周易的程序员1 天前
aiDgeScanner架构与实现
c++·ide·物联网·架构·node.js·aiot