node常用fs文件操作方法

关键术语

硬链接

硬链接是文件系统中的一种特殊机制,允许多个文件名指向同一文件的物理数据块 。每个硬链接共享相同的 inode(索引节点, 用于存储文件或目录的元数据, 通过唯一的 inode 编号 标识每个文件系统对象 ,即这些文件名本质上是同一文件的不同入口。例如,文件 file.txt 创建硬链接 link.txt 后,两者指向同一数据,修改任一文件内容都会同步到另一个文件。

符号链接

实质

是文件系统中的一种特殊文件(如Linux的l类型文件,Windows的.symlink),其核心功能是通过路径引用指向另一个文件或目录。与快捷方式相似但不是一个东西。

作用

  • 符号链接本身不存储实际数据,仅包含目标文件或目录的绝对/相对路径字符串。操作系统会自动将对其的读写操作重定向到目标文件
  • 删除符号链接不会影响目标文件;但若目标被删除或移动,符号链接会变为"悬空链接"(Dangling Link),访问时会报错

与硬链接的对比

特性 符号链接 硬链接
存储内容 目标路径 目标文件的 inode
跨文件系统 支持 不支持
目标删除后 变为悬空链接 仍可访问(文件数据保留)
目录支持 支持 不支持(仅限文件)
命令示例 ln -s target link ln target link

作用

进行文件的读写。

使用前提

需要先引用 fs

ini 复制代码
const fs = require('fs')

文件系统标志

是之后 API 中 flag 参数的值

追加模式(Append Modes)

  • 'a'以追加模式打开文件,文件不存在时自动创建。写入操作始终从文件末尾开始。
    示例:日志文件的持续写入
  • 'ax'类似 'a',但若文件已存在则抛出错误。用于防止意外覆盖现有文件
  • 'a+'追加并读取模式。文件不存在时创建,支持同时读写操作,但写入时仍从文件末尾开始
  • 'ax+'类似 'a+',但文件已存在时抛出错误
  • 'as''as+'同步模式的追加操作('as' 仅追加,'as+' 可追加和读取)。文件不存在时创建。

注意:'as''as+'标志不会使 fs.open() 变为同步阻塞调用,仅改变操作系统层面的 I/O 行为。

读取模式(Read Modes)

  • 'r' 只读模式打开文件。若文件不存在则抛出异常。
  • 'rs' 同步模式读取文件(绕过系统缓存)。适用于需要强制从磁盘读取最新数据的场景,但会显著降低性能。
  • 'r+' 读写模式。文件必须存在,否则抛出异常。
  • rs+ 同步读写模式,强制绕过本地文件系统缓存。主要用于NFS挂载文件的访问,避免读取过期的本地缓存数据。

警告:rs+ 模式可绕过本地缓存,适用于网络文件系统(如 NFS)的场景,对I/O性能影响较大,非必要不推荐使用。

写入模式(Write Modes)

  • 'w'写入模式。文件不存在时创建,存在时清空内容(Truncate)
  • 'wx'类似 'w',但文件已存在时抛出错误。用于确保不会覆盖现有文件
  • 'w+'读写模式。文件不存在时创建,存在时清空内容
  • 'wx+'与 'w+' 类似,但文件已存在时抛出错误

背诵技巧

只有 w 无 s ,每个标志都有 + 模式,+ 模式表示读写。

x 表示文件存在则抛出错误,但是 r 本身需要文件存在所以无 x

a 文件末尾改写,w 清空改写,二者皆可创建文件

常见错误码:

  • EBADF:无效文件描述符。
  • ENOSPC:磁盘空间不足。
  • EINTR:写入被信号中断。
  • EEXIST:目录已存在且 recursive=false
  • ENOENT:路径中某部分非目录且 recursive=false
  • EPERM:权限不足(如 Windows 创建根目录)

文件基础操作

fs.open 打开文件

作用

异步打开文件,在文件打开后,可以拿取文件对应的文件描述符,这样就可以通过描述符对文件内容进行操作。

语法

  • path string | Buffer | URL
    文件路径,支持字符串、Buffer 或 URL 对象。
  • flags string | number
    文件系统标志,控制打开方式。默认值:'r'(只读模式)。
  • mode string | integer
    设置文件权限(仅当文件被创建时生效),默认值:0o666(可读可写)。
  • callback Function
    回调函数,接收两个参数:
    • err Error:操作错误信息。
    • fd integer:文件描述符,用于后续操作(如读写)。

fs.close 关闭文件

作用

用于关闭文件描述符,以此来释放资源,防止文件描述符泄露。

语法

参数 类型 必填 说明
fd integer 文件描述符,由 fs.open()fs.openSync()返回
callback Function 操作完成后执行的回调,仅接收可能的错误信息 err。未提供时操作异步执行
  • 若文件描述符 fd 正在被其他异步操作(如并发读取或写入)使用,调用 fs.close() 会导致未定义行为
  • 若是重复关闭则会报错

cookbook

同一文件描述符多次调用 fs.close() 会抛出 EBADF 错误,可通过标志位跟踪关闭状态

常见错误类型:

  • EBADF: 无效的文件描述符(如已关闭或未打开)。
  • EIO: 底层 I/O 错误(如磁盘故障)
ini 复制代码
const safeClose = (function () {
  let isClosed = false;
  return function(fd) {
    if (!isClosed) {
      fs.close(fd, (err) = {
        if (!err) isClosed = true;
      });
    }
  }
})();

fs.fsync 强制刷新缓冲磁盘

作用

将文件描述符 fd 对应的所有数据刷新到存储设备中,确保数据持久化。这样可以使得其他并发打开文件的设备可以观察到文件修改后的内容。

语法

scss 复制代码
fs.fsync(fd, callback)
  • fd integer 已打开的文件描述符。
  • callback Function 操作完成后的回调函数,仅接收一个可能的异常参数 err。

cookbook

在文件关闭前,若是对文件内容进行过修改,必须强制刷新下磁盘,确保数据被存储在磁盘中,防止数据丢失。

获取文件元信息

文件元信息 stats 对象的关键属性及方法

  • size 文件字节大小
  • mtime 最后修改时间(Date 对象)
  • birthtime 创建时间(Date 对象)
  • mtimeMs 最后修改时间(时间戳)
  • birthtimeMs 创建时间(时间戳)
  • isFile() 是否为一个文件
  • isDirectory() 是否为目录。
  • isSymbolicLink() 是否为符号链接

fs.stat 文件、目录元数据

作用

异步获取指定路径资源的元数据信息。

语法

fs.stat(path[, options], callback)

参数

  • path 可以为 string 资源路径,Buffer 二进制数据或URL 对象。
  • options 配置选项,属性如下:
    • bigint: boolean ,默认为 false ,表示使用用 BigInt 类型返回元信息中的数字数据。
  • callback 在获取到元数据信息后的回调函数
    • err 获取失败的错误信息【路径不对、权限不足等】
    • stats 资源的元数据对象

处理符号链接

fs.stat() 会跟随符号链接获取目标文件的元数据。

那么就代表 stats.isSymbolicLink() 永远返回 flase

若需获取链接本身的元数据,需使用 fs.lstat()

cookbook

  • 不推荐在使用 open 或是 readFile 前使用该方法检测文件是否存在,推荐直接进行文件操作并处理错误。单纯检查存在性用 fs.access

fs.promises.stat()

与 fs.stat() 语法类似,但是无回调,相当于 fs.stat() 的 promise 返回值版,promise 返回值为 callback 的第二个参数

fs.lstat()

用法

与 fs.stat 一致,但是在处理符号链接时,会返回符号链接本身的元数据

应用场景:

  • 监控符号链接的状态变化(如链接是否被修改)****。
  • 检查符号链接的权限是否符合安全要求。

fs.promises.lstat()

与 fs.lstat() 语法类似,但是无回调,相当于 fs.lstat() 的 promise 返回值版,promise 返回值为 callback 的第二个参数

fs.fstat 获取已打开文件元信息

语法

css 复制代码
fs.fstat(fd[, options], callback)
  • fd integer

与 fs.stat 功能语法类似,但是第一个参数为 通过 fs.open()fs.openSync() 方法获取的文件描述符【一个整型数字】。

fs.promises.fstat()

与 fs.fstat() 语法类似,但是无回调,相当于 fs.fstat() 的 promise 返回值版,promise 返回值为 callback 的第二个参数

文件夹增改查

fs.mkdir 创建文件夹

作用

异步方法,用于创建目录并设置目录权限

语法

fs.mkdir(path[, options], callback)

  • path string | Buffer | URL
  • options Object | integer 是数字则仅仅设置文件夹元数据的 mode 属性,对象则表示配置对象,属性如下:
    • recursive 若父目录不存在,是否递归创建,默认 flase
    • mode string | integer 默认值: 0o777(最高权限,实际受 umask 限制)
  • callback 执行命令后的回调函数,参数如下:
    • err 错误对象
    • path 仅在 recursive 为 true 的时候存在,表示首个被创建的目录路径,若是目录已存在且无需新建则为 undefined

fs.promises.mkdir()

与 fs.mkdir() 语法类似,但是无回调,相当于 fs.mkdir() 的 promise 返回值版,promise 返回值为 callback 的第二个参数

写文件

fs.writeFile 创建并写入文件

应用场景

适用于一次性写入较小数据的场景

作用

异步方法,用于将数据完整写入文件。

  • 当使用非文件描述符来指定文件时,在不指定操作标记时,操作同 w 。指定了操作标记时则按照操作标记来进行操作
  • 该方法是从文件的指针位置开始覆盖文件内容,所以可能会造成文件中部分内容被覆盖的情况。
  • file 为文件描述符(通过 fs.open 获取)时,行为类似直接调用 fs.write(),但会自动重试直到数据完全写入。

语法

fs.writeFile(file, data[, options], callback)

  • file string | Buffer | URL | integer 目标文件路径 或 文件描述符(File Descriptor)。
  • data string | Buffer | TypedArray | DataView 要写入的数据,支持字符串、二进制缓冲区等格式。
  • options Object | string 若是字符串则 指定 flag 【打开方式 】,若是对象则是配置对象,属性如下:
    • encoding string | null 编码格式,默认: 'utf8'。若 data 是 Buffer 或二进制类型,此选项被忽略。
    • mode integer 文件权限(类 Unix 系统),默认: 0o666(可读可写)。
    • flag string 文件操作标志(如 'w' 写入、'a' 追加),默认: 'w'(覆盖写入)。
    • flush boolean 写入完成后是否调用 fs.fsync() 强制刷盘,默认: false。启用后(flush: true),调用 fs.fsync() 确保数据写入物理磁盘,避免系统缓存丢失。
    • signal AbortSignal 允许通过 AbortController 中断写入操作,但无法回滚已写入的数据。

cookbook

  • 适用于一次性写入较小数据的场景,每次写入开启 flush 防止内容丢失。
  • 大文件写入时,fs.writeFile 会一次性加载所有数据到内存。建议使用流式写入(fs.createWriteStream)分块处理。

fs.promises.writeFile()

与 fs.writeFile() 语法类似,但是无回调,相当于 fs.writeFile() 的 promise 返回值版,promise 返回值为 undefined

fs.write() 写入文件指定内容

作用

异步方法用于像文件内覆盖写入内容

语法

写入二进制数据
普通写法
arduino 复制代码
fs.write(fd, buffer, offset[, length[, position]], callback)
  • fd integer:文件描述符
  • buffer Buffer | TypedArray | DataView :要写入的二进制数据
  • offset integer Default: 0:buffer 中要写入数据的起始偏移量
  • length integer Default: buffer.byteLength - offset 要写入的数据长度
  • position integer | null Default: null 文件写入位置
  • callback Function 写入后的回调函数,参数如下:
    • err Error
    • bytesWritten integer 表示从缓冲区实际写入的字节数。
    • buffer Buffer | TypedArray | DataView 源数据,与传入的 buffer 参数是同一个内存空间
选项写法
arduino 复制代码
fs.write(fd, buffer[, options], callback)

其余的与普通写法一致,但是 options 为一个配置对象,相当于将中间三个可选项集合成一个配置对象:

  • offset integer Default: 0
  • length integer Default: buffer.byteLength - offset
  • position integer Default: null
写入字符串
lua 复制代码
fs.write(fd, string[, position[, encoding]], callback)
  • fd integer:文件描述符
  • string string:要写入的字符串
  • position integer | null Default: null,表示从文件开头计算的写入位置偏移量。如果类型不是数字,数据将写入当前光标位置
  • encoding string Default: 'utf8' 指定字符串编码格式。
  • callback Function 写入操作后的回调,参数如下
    • err Error:写入错误后的报错
    • written integer 已写入字节数
    • string string 要写的字符串

cookbook

在没有等待回调的情况下多次调用 fs.write() 操作同一文件是不安全的,原因如下:

  • 写入顺序不可控
    • Node.js 的异步 I/O 机制意味着多次 fs.write() 调用可能以不可预测的顺序执行。若未通过回调等待前一次写入完成,可能导致后一次写入覆盖前一次的数据
  • 文件位置(position)冲突
    • fs.write()position 参数需要手动管理。若未显式指定或计算错误,多个异步写入可能定位到同一文件位置,导致数据覆盖(类似 C 语言中非追加模式下的 fwrite 问题)
  • 缓冲区的竞争条件
    • 底层 I/O 操作通常依赖缓冲区。若多个异步写入同时操作缓冲区,可能因未同步刷新(如未调用类似 fflush() 的机制)导致数据未及时落盘,甚至进程崩溃时数据丢失

建议使用 fs.createWriteStream()。

fs.createWriteStream()

作用

用于创建可写流,适用于大数据写入和非阻塞 I/O 操作场景。

语法

css 复制代码
fs.createWriteStream(path[, options])
参数
  • path:string / Buffer / URL,必填,目标文件路径【要写入内容的文件的路径】
  • options: string / Object,默认值 {}, 若为字符串则表示编码格式。
  1. flags
      • 类型:string
      • 默认值:'w'(覆盖写入)
      • 可选值:'a'(追加)、'r+'(读写模式)等
  1. encoding
      • 类型:string
      • 默认值:'utf8'
      • 支持编码:'ascii''base64'等,若设为 null 则返回 Buffer
  1. mode
      • 类型:integer
      • 默认值:0o666(可读写权限)
      • 作用:设置文件权限(如 0o644 表示用户可读写,其他只读)
  1. start
      • 类型:integer
      • 范围:[0, Number.MAX_SAFE_INTEGER]
      • 功能:指定写入起始字节位置(如从第 100 字节开始写)
  1. autoClose
      • 类型:boolean
      • 默认值:true
      • 作用:流结束时自动关闭文件描述符,避免内存泄漏
  1. highWaterMark
      • 类型:number
      • 默认值:16384(16KB)
      • 功能:设置内部缓冲区大小,控制背压(Backpressure)【下游处理能力不足时,向上游反馈信号以降低数据生产速率】
  1. fd
      • 类型:integer / FileHandle
      • 默认值:null
      • 说明:若指定文件描述符,则忽略 path 参数且不触发 'open' 事件
  1. fs
      • 类型:Object / null
      • 默认值:null
      • 功能:覆盖底层文件系统实现(需至少重写 writewritev 方法)
  1. emitClose
      • 作用:用于控制流在销毁时是否触发 'close' 事件。
      • 默认值:true(自动触发)
返回值

一个继承自 stream.Writable 类的 fs.WriteStream 对象。该对象用于以流式方式高效写入文件。

fs.WriteStream 对象

继承

该对象继承自 stream.Writable

Stream | Node.js v23.11.0 Documentation

事件
  • close :流关闭且底层文件描述符已释放时触发
  • open:文件成功打开后触发,可通过回调参数 fd 获取文件描述符
  • ready: 在 'open' 事件之后立即触发。 表示流已完成初始化,可以安全调用写入方法
属性及方法
  • writeStream.bytesWritten: 已写入的字节数
  • writeStream.path :流写入的文件路径(即 fs.createWriteStream() 的第一个参数)。

若路径是字符串,则此属性为字符串;若路径是 Buffer,则此属性为 Buffer。

  • writeStream.pending : 若底层文件尚未打开(在 'ready' 事件触发前),此属性为 true。用于检查流的初始化状态,避免在文件未打开时执行写入操作
  • writeStream.close([callback]) : 关闭 writeStream。若提供回调函数,则会在流关闭后执行。

autoClose: true(默认),此方法会自动关闭文件描述符并触发 'close' 事件

写入方法的选择

指标 writeFile appendFile createWriteStream write
文件打开次数 每次调用 每次调用 单次打开持续写入 需手动管理
内存占用 低(分块处理)
高频写入效率 优(背压支持) 优(需优化)
二进制处理能力 一般 一般
arduino 复制代码
是否需精确控制写入位置?
├─ 是 → fs.write + Buffer 操作
└─ 否 → 是否高频?
    ├─ 是 → createWriteStream
    └─ 否 → 是否需要追加内容?
        ├─ 是 → 数据规模?
        │   ├─ 小文件 → appendFile
        │   └─ 大文件 → createWriteStream + { flags: 'a' }
        └─ 否 → 数据规模?
            ├─ 小文件 → writeFile
            └─ 大文件 → createWriteStream

感觉精细操作用 write ,剩下的无脑用 createWriteStream 就可以

拷贝、剪切文件

fs.rename 剪切文件

作用

异步将文件从 oldPath 重命名或移动到 newPath,在多数文件系统中,重命名操作是原子性的,即要么完全成功,要么完全失败,无中间状态。

  • newPath 已存在且为文件,则删除源文件。将源文件内容覆盖目标文件内容。
  • newPath 指向目录(无论是否为空),操作将失败并抛出错误。
  • 否则,相当于剪切源文件,粘贴至新位置。

语法

lua 复制代码
fs.rename(oldPath, newPath, callback)
  • oldPath string | Buffer | URL
    原文件路径(支持字符串、Buffer 或 URL 对象)。
  • newPath string | Buffer | URL
    新文件路径(若路径指向目录或路径不存在则会抛出错误)。
  • callback Function
    操作完成后的回调函数,仅接收一个可能的异常参数 err

fs.copyFile拷贝文件

作用

异步将 src 文件复制到 dest。默认情况下,若 dest 已存在则会被覆盖。

语法

css 复制代码
fs.copyFile(src, dest[, mode], callback)

参数

  • src string | Buffer | URL 要复制的源文件路径
  • dest string | Buffer | URL 复制操作的目标文件路径
  • mode integer用于控制复制行为,默认为 0 ,即若 dest 已存在则会被覆盖。可通过 位或运算 (|) 组合多个常量:
  1. fs.constants.COPYFILE_EXCL
      • dest 已存在,则复制操作失败(类似 O_EXCL 标志)。
  1. fs.constants.COPYFILE_FICLONE可极大提升大文件复制性能。
      • 尝试创建 写时复制(Copy-on-Write)引用链接【延迟复制操作到真正需要修改数据时,从而减少不必要的资源消耗】。若平台不支持写时复制,则回退到普通复制机制。
  1. fs.constants.COPYFILE_FICLONE_FORCE
      • 强制尝试创建写时复制引用链接。若平台不支持,则操作直接失败。
  • callback Function 完成操作后的回调,复制操作可能在中途失败,导致目标文件部分写入(需自行处理残留文件)。
    • err Error

文件及文件夹的删除

作用

异步删除文件或符号链接。无法删除目录

  • 删除操作实际是减少文件的硬链接计数,当计数归零且无进程打开文件时,存储空间才会释放****。
  • 若文件正在被其他进程使用,删除操作仅移除路径入口,数据仍保留至所有进程关闭文件

语法

lua 复制代码
fs.unlink(path, callback)
  • path string | Buffer | URL 要删除的文件或符号链接路径
  • callback Function 操作完成时回调
    • err Error

cookbook

使用时实现删除错误重试

scss 复制代码
// 删除失败时重试(示例)
function safeUnlink(path, retries = 3) {
  fs.unlink(path, (err) = {
    if (err && retries  0) {
      setTimeout(() = safeUnlink(path, retries - 1), 100);
    }
  });
}

fs.rmdir 删除文件夹【已废弃,仅兼容旧代码】

作用

异步方法,用于删除目录

语法

fs.rmdir(path[, options], callback)

与 fs.mkdir() 语法类似,但是回调无第二个参数

fs.promises.rmdir()

与 fs.rmdir() 语法类似,但是无回调,相当于 fs.rmdir() 的 promise 返回值版,promise 返回值为 undefined

fs.rm 递归删除文件夹以及文件

语法
css 复制代码
fs.rm(path[, options], callback)
  • path string | Buffer | URL 要删除的文件或目录路径
  • options Object 可配置选项
    • force boolean 设为 true 时,若路径不存在则忽略异常。默认值:false
    • maxRetries integer表示错误时最大重试次数,仅在 recursivetrue 时生效。 当遇到 EBUSYEMFILEENFILEENOTEMPTYEPERM 错误时,Node.js 会以线性退避策略重试操作(每次重试间隔时间递增 retryDelay 毫秒)。默认值:0
    • recursive boolean 设为 true 时,递归删除目录及其内容。失败时会自动重试。默认值:false
    • retryDelay integer 每次重试的间隔时间(单位:毫秒)。仅在 recursivetrue 时生效。默认值:100
  • callback Function
    • err Error

文件及文件夹的读取

注意事项

读取 base64 格式的图片数据时,读取到的仅仅是图片的数据,不能直接用来展示图片,要展示需要在前面增加 base64 头才可 data:图片MIMEType;base64,

比如一个 jpg 图片 base64 数据为 jkhciquuihdiuhjkwddj2i1h2iuh3iu2hjkhskudiqowudh

那么要使用时,应该用 data:image/jpg;base64,jkhciquuihdiuhjkwddj2i1h2iuh3iu2hjkhskudiqowudh才能展示图片

fs.createReadStream 流读取

作用

以流的形式读取文件内容

语法

css 复制代码
fs.createReadStream(path[, options])

参数

  • path string | Buffer | URL
    文件路径,支持字符串、Buffer 或 URL 对象。
  • options string | Object
    可选配置项,可指定编码或文件读取范围等:
    • flags string
      文件系统标志(如 'r' 表示只读,'w+' 表示读写)。默认值:'r'
    • encoding string
      指定读取数据的字符编码。默认值:null(返回 Buffer)。
    • fd integer | FileHandle
      已打开的文件描述符或 FileHandle 对象。若指定,将忽略 path 参数且不触发 'open' 事件。默认值:null
    • mode integer
      设置文件模式(权限和 sticky 位),仅在创建文件时生效。默认值:0o666
    • autoClose boolean
      是否在流关闭时自动关闭文件描述符。默认值:true
    • emitClose boolean
      是否在流销毁后触发 'close' 事件。默认值:true
    • start integer
      读取起始字节位置(包含该字节)。
    • end integer
      读取结束字节位置(包含该字节)。默认值:Infinity
    • highWaterMark integer
      控制内部缓冲区的最大字节数。默认值:64 * 1024(64KB)。
    • fs Object | null
      可覆盖默认的 fs 模块方法(如 openreadclose)。默认值:null
    • signal AbortSignal | null
      允许中止读取操作。默认值:null

返回值:fs.ReadStream(可读流对象)

fs.ReadStream

继承

继承自 stream.Readable

Stream | Node.js v23.11.0 Documentation

事件
  • close 关闭时触发
  • open 当文件描述符打开的时候触发,接收一个参数,该参数为当前流对应文件的文件描述符
  • ready 在 open 之后立即触发
属性
  • bytesRead :当前已经读取的字节数
  • path : 正在读取流的源文件路径,具体值的类型与 createReadStream 的第一个参数有关,可能有三种值:
    • 若 path 【第一个参数】为字符串,则该属性的值为字符串
    • 若为 Buffer 则该属性为 Buffer
    • 若为文件描述符,则该属性为 undefined
  • pending:表示文件是否尚未打开

fs.readdir 读取文件夹下文件信息

语法

css 复制代码
 fs.readdir(path[, options], callback)  
  • path string | Buffer | URL
    目标目录的路径。
  • options string | Object
    可选配置项,可指定字符编码或高级读取模式:
    • encoding string
      指定返回文件名使用的字符编码,默认值:'utf8'。若设为 'buffer',文件名将以 Buffer 对象形式返回。
    • withFileTypes boolean
      设为 true 时,返回的 files 数组将包含 fs.Dirent 对象(而非字符串),用于获取文件类型信息。默认值:false
    • recursive boolean
      设为 true 时,递归读取目录内容(包括子目录和嵌套文件)。默认值:false
  • callback Function
    回调函数,接收两个参数:
    • err Error 操作中可能抛出的错误。
    • files string[] | Buffer[] | fs.Dirent[]
      目录内文件名数组(不包括 ...)。具体类型由 options 配置决定。

fs.readFile 读取整个文件内容

语法

css 复制代码
fs.readFile(path[, options], callback)
  • path string | Buffer | URL | integer
    目标文件路径或文件描述符(支持字符串、Buffer、URL 或文件描述符整数)。
  • options Object | string
    可选配置项,可指定编码、文件标志或中止信号,不指定则返回原始 Buffer:
    • encoding string | null
      指定返回数据的字符编码。默认值:null(返回原始 Buffer)。若设为 'utf8' 等编码,则返回字符串。
    • flag string
      文件系统标志(如 'r' 表示只读,'w+' 表示读写)。默认值:'r'
    • signal AbortSignal
      允许中止进行中的读取操作(需配合 AbortController 使用)。
  • callback Function
    回调函数,接收两个参数:
    • err Error | AggregateError 操作中可能抛出的错误。
    • data string | Buffer 文件内容,类型由 encoding 参数决定。

fs.read 高性能文件读取

语法

arduino 复制代码
fs.read(fd, buffer, offset, length, position, callback)
  • fd integer
    通过 fs.open 打开的文件描述符。
  • buffer Buffer | TypedArray | DataView
    数据将被写入的缓冲区。
  • offset integer
    缓冲区中开始写入数据的偏移量(以字节为单位)。
  • length integer
    期望读取的最大字节数。
  • position integer | bigint | null
    文件读取的起始位置:
    • 若为 null-1,从当前文件位置读取,并更新文件位置指针。
    • 若为非负整数,从指定位置读取,且文件位置指针保持不变。
  • callback Function
    回调函数,接收三个参数:
    • err Error 操作中可能抛出的错误。
    • bytesRead integer 实际读取的字节数(可能小于 length)。
    • buffer Buffer 被写入数据的缓冲区引用。
css 复制代码
fs.read(fd[, options], callback)

上面语法的选项版本,options 的属性有 buffer,offset, length, position ,含义与上方一致

arduino 复制代码
fs.read(fd, buffer[, options], callback)

将 options 中的 buffer 属性放置在第二个参数。

文件内容读取操作cookbook

  • 在进行大文件读取或是高并发场景时,使用流式读取(fs.createReadStream())。
  • 高性能场景, 直接使用 fs.read() 手动管理读取过程,复用 Buffer 减少中间缓冲开销

文件的监听

应用实例

脚手架中的热更新就是使用 watch 或 fs.watchFile 实现监听文件变更的。

fs.watchFile 低性能高兼容轮询监听单文件

作用

采用轮询检测的方式去检查文件或文件夹状态,若是文件修改则会触发监听事件。

  • 当文件不存在时(ENOENT 错误),回调函数会触发一次,所有字段置零(时间戳设为 Unix 纪元)。
  • 若文件后续被创建,会再次触发回调,此时 current 为最新状态。
  • 无法检测重命名

语法

css 复制代码
fs.watchFile(filename[, options], listener)

无对应的 promise 版本方法

参数:

  • filename string | Buffer | URL
    要监视的文件路径。
  • options Object
    可选配置项:
    • bigint boolean
      是否以 BigInt 格式返回数值(如文件大小、时间戳)。默认值:false
    • persistent boolean
      是否保持进程持续运行(只要监视在运行)。默认值:true
    • interval integer
      轮询文件状态的间隔时间(毫秒)。默认值:5007
  • listener Function
    文件状态变化时的回调函数,接收两个参数:
    • current fs.Stats 当前文件状态。
    • previous fs.Stats 先前文件状态。

返回值fs.StatWatcher 监视器对象,可用于停止监视。

如何关闭监听

使用 fs.unwatchFile

css 复制代码
fs.unwatchFile(filename[, listener])

参数

  • filename string | Buffer | URL
    要停止监视的文件路径。
  • listener Function
    可选参数,指定要移除的监听器(需与 fs.watchFile() 绑定的回调函数一致)。

作用

  • 若是传入listener则只会移除 listener 对应的监听,若是不传,则移除该文件所有监听。
  • 若文件 filename 未被监视,调用此方法不会报错,也不执行任何操作。

fs.watch 高性能事件驱动递归监听文件

作用

递归监听目录或文件的改变,使用操作系统事件通知,所以更为高效,但是兼容性差

语法

css 复制代码
fs.watch(filename[, options][, listener])
  • filename string | Buffer | URL
    要监视的文件或目录路径。
  • options string | Object
    可选配置项(若为字符串,则指定字符编码):
    • persistent boolean
      是否保持进程持续运行(只要监视器在运行)。默认值:true
    • recursive boolean
      是否递归监视子目录(仅部分平台支持目录监视)。默认值:false
    • encoding string
      指定传递给监听器的文件名编码。默认值:'utf8'
    • signal AbortSignal
      允许通过 AbortSignal 关闭监视器。
  • listener Function | undefined
    事件监听回调函数,接收两个参数:
    • eventType string:事件类型('rename''change')。
    • filename string | Buffer | null:触发事件的文件名(可能为空)。

返回值fs.FSWatcher

监视器对象,可监听事件或关闭监视。

参数解析

参数 类型 必填 说明
filename string/Buffer/URL 目标文件或目录路径。
options string/Object 配置项(字符编码或对象)。
listener Function 事件回调函数,接收 eventTypefilename参数。

平台实现差异

系统 底层机制
Linux 使用 inotify监控文件系统事件。
macOS 文件使用 kqueue,目录使用 FSEvents
Windows 依赖 ReadDirectoryChangesWAPI。
BSD/SunOS BSD 使用 kqueue,SunOS(含 Solaris 和 SmartOS)使用 event ports
AIX 需启用 AHAFS功能。
IBM i 不支持此功能。
  1. Windows 特有行为
  • 监视的目录被移动或重命名时不会触发事件。
  • 删除被监视的目录会抛出 EPERM 错误。
  1. listener 中 文件名参数( filename
  • 支持平台:Linux、macOS、Windows、AIX。
  • 可能为空 :即使在这些平台,filename 也可能为 null
  1. Linux/macOS
  • 文件删除后重建会分配新 inode,原监视器仅触发删除事件,不跟踪新文件。
  1. AIX
  • 保存并关闭文件会触发两次事件(内容添加和截断)。

如何关闭监听

  • 使用 AbortControl 来进行关闭。
ini 复制代码
const controller = new AbortController();  
const watcher = fs.watch('file.txt', { signal: controller.signal });  
controller.abort(); // 关闭监视器  
  • watcher.close()关闭
ini 复制代码
const controller = new AbortController();  
const watcher = fs.watch('file.txt', { signal: controller.signal });  
watcher.close()

cookbook

  • 优先使用 fs.watch ,因为性能好,事件驱动。若是报错则使用 fs.watchFile
  • 在监听后使用 unwatchFile 等方法取消监听释放资源。

文件方法的 promise 版

哪些 api 有 promise 版

当前文档中所有的方法都是异步的,除了 fs.watchFile 、fs.unwatchFile,剩下的 都有对应的 promise 版方法。

使用方法

若是不需要传递 fd 参数,那么使用方式为 fs.promise.方法名

否则为 filehandle.方法

参数

参数与普通方法类似,但是有以下不同

  • 不需要传递 callback , callback 除了 err 剩余所有参数都会被包成一个对象作为期约成功兑现的结果 ,err 则会作为期约拒绝时的理由。
  • 不需要传递 fd ,而是改为使用 filehandle.方法 的形式调用方法,返回期约。filehandle 则是通过 promise 版本的 fs.open 方法拿到的期约兑现结果。

返回值

返回一个期约

示例

不需要传递 fd 的

javascript 复制代码
const fs = require('fs/promises'); // 或者 require('fs').promise
fs.open('./text.txt', 'r').then(async (res) => {
});

需要传递 fd 的

javascript 复制代码
const  { randomFillSync } = require("crypto");
console.log(Buffer)
const fs = require('fs/promises');
const { Buffer: NodeBuffer } = require('buffer');
fs.open('./text.txt', 'r').then(async (res) => {
    // res 为 filehandle

    const buf = NodeBuffer.allocUnsafe(10);
    randomFillSync(buf, 0, 10);
    buf.fill(0);
    const r = await res.read(buf, 0, 10, 0); // 这里
    console.log(r, buf);
});
相关推荐
GISer_Jing9 分钟前
前端面试通关:Cesium+Three+React优化+TypeScript实战+ECharts性能方案
前端·react.js·面试
落霞的思绪1 小时前
CSS复习
前端·css
咖啡の猫3 小时前
Shell脚本-for循环应用案例
前端·chrome
百万蹄蹄向前冲5 小时前
Trae分析Phaser.js游戏《洋葱头捡星星》
前端·游戏开发·trae
朝阳5816 小时前
在浏览器端使用 xml2js 遇到的报错及解决方法
前端
GIS之路6 小时前
GeoTools 读取影像元数据
前端
ssshooter7 小时前
VSCode 自带的 TS 版本可能跟项目TS 版本不一样
前端·面试·typescript
你的人类朋友7 小时前
【Node.js】什么是Node.js
javascript·后端·node.js
Jerry7 小时前
Jetpack Compose 中的状态
前端
dae bal8 小时前
关于RSA和AES加密
前端·vue.js