fs模块

102 阅读7分钟

文件读取

nodejs 中的文件读取,支持异步读取以及同步读取

  • 异步读取

    fs.readFile(path[, options], callback)
    • path: string | Buffer | URL | integer 文件名或文件描述符

    • options: (这是一个可选项) object<encoding | flag | signal> | string

      其中 encoding: string | null 是读取文件的编码格式, 默认值为 null

      flag: string 是支持的文件系统 flags, 默认值是 'r'

      signal: AbortSignal 允许中止正在进行中的 readFile

    • callback: function , 有两个回调参数 err, data

      err: 错误消息

      data: string | buffer

const { readFile } = require("node:fs");
const path = require("node:path");

readFile(path.resolve(__dirname, "./观书有感.txt"), "utf-8", (err, data) => {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});

promise 类型的 readFile
// 使用 promises 去读取文件
fs.readFile(path.resolve(__dirname, "./观书有感.txt"), "utf-8").then(
  (data, err) => {
    if (err) {
      console.log(err);
    } else {
      console.log(data);
    }
  }
);

返回的是一个 promise 类型的数据

文件可读流 fs.createReadStream(path[, options])

js 中的事件都继承至 eventEmitter, 我们可以通过这个事件中的方法监听数据流


const readStram = createReadStream(path.resolve(__dirname, "./观书有感.txt"));

readStram.on("data", (chunk) => {
  // 返回的是 Buffer 数据
  console.log(chunk);
  console.log(chunk.toString());
});
readStram.on("end", () => {
  console.log("读取完成");
});
readStram.on("error", (err) => {
  console.log(err);
});

总结

所有的异步读取文件的 api 都有一个回调函数, 这个回调函数包含了读取的结果和错误异常

同时可选配置项中的 flag 支持多种选择配置, 默认值为 r

  • 可选配置项

    • 'a':打开文件进行追加。如果文件不存在,则创建该文件。

    • 'ax':类似于 'a' 但如果路径存在则失败。

    'ax': Like 'a' but fails if the path exists.

    • 'a+':打开文件进行读取和追加。如果文件不存在,则创建该文件。

    • 'ax+':类似于 'a+' 但如果路径存在则失败。

    • 'as':以同步模式打开文件进行追加。如果文件不存在,则创建该文件。

    • 'as+':以同步模式打开文件进行读取和追加。如果文件不存在,则创建该文件。

    • 'r':打开文件进行读取。如果文件不存在,则会发生异常。

    • 'rs':打开文件以同步模式读取。如果文件不存在,则会发生异常。

    • 'r+':打开文件进行读写。如果文件不存在,则会发生异常。

    • 'rs+':以同步模式打开文件进行读写。指示操作系统绕过本地文件系统缓存。

    这主要用于在 NFS 挂载上打开文件,因为它允许跳过可能过时的本地缓存。它对 I/O 性能有非常实际的影响,因此除非需要,否则不建议使用此标志。

    这不会将 fs.open() 或 fsPromises.open() 变成同步阻塞调用。如果需要同步操作,应该使用类似 fs.openSync() 的东西。

    • 'w':打开文件进行写入。创建(如果它不存在)或截断(如果它存在)该文件。

    • 'wx':类似于 'w' 但如果路径存在则失败。

    • 'w+':打开文件进行读写。创建(如果它不存在)或截断(如果它存在)该文件。

    • 'wx+':类似于 'w+' 但如果路径存在则失败。

  • 同步读取

    readFileSync 添加上 Sync 代表它为同步读取文件, 但是如果文件读取过大会等待很长时间, 建议使用异步读取的方式获取文件

文件写入

nodejs 中的文件写入,支持异步读取以及同步读取

  • 异步写入
fs.writeFile(file, data[, options], callback)

file: string | Buffer | URL | integer 文件名或文件描述符

data: string>| Buffer| TypedArray | DataView

options: Object | string

  • encoding  |  默认值:'utf8'

  • mode  默认值:0o666

  • flag  参见 支持文件系统 flags。默认值:'w'

  • flush  如果所有数据都成功写入文件,并且 flush 是 true,则使用 fs.fsync() 来刷新数据。默认值:false

  • signal  允许中止正在进行的 writeFile

    
const data = Buffer.from("hello world");
  
writeFile(
  path.resolve(__dirname, "./观书有感.txt"),
  //"追加内容",
  data,
  { flag: "a" },
  (err) => {
    if (err) {
      console.log(err);
    } else {
      console.log("写入成功");
    }
  }
);
promise 类型的 writeFile
const fs = require("node:fs/promises");

const data = Buffer.from("hello world");
fs.writeFile(path.resolve(__dirname, "./观书有感.txt"), data, { flag: "a" })
  .then(() => {
    console.log("写入成功");
  })
  .catch((err) => {
    console.log(err);
  });
  • 同步写入

writeFileSync 添加上 Sync 代表它为同步写入文件

writeFileSync(path.resolve(__dirname, "./观书有感.txt"), "写入成功", {
  flag: "a",
});
文件写入流 fs.createWriteStream([options])
const writeStream = createWriteStream(
  path.resolve(__dirname, "./观书有感.txt"),
  {
    flags: "a",
  }
);

writeStream.write("\n 写入流");
writeStream.end();
writeStream.on("finish", () => {
  console.log("写入完成");
});

文件读写流可以通过 pipe 管道进行写入

const resadStream = fs.createReadStream('./观书有感.txt')
const writeStream = fs.createWriteStream('./观书有感2.txt')
    
// 这句话的意思是 将 resadStream 中的数据写入到 writeStream
resadStream.pipe(writeStream)

总结:

文件如果不存在, 他会帮我们创建并写入

  • writeFile // 异步写入 四个参数, 第一个为文件路径 第二个为写的内容, 第三个是可选项配置, 第四个是回调函数
  • writeFileSync // 同步写入
  • appendFile // 异步追加写入
  • appendFileSync // 同步追加写入
  • createWriteStream // 创建写入流

文件写入的场景: - 下载文件 - 安装软件 - 保存程序日志, 如 git - 编辑器保存文件 - 视频录制等

当需要持久化保存数据的时候, 应该想到文件写入

文件夹操作

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

    三个参数:第一个为文件夹路径, 第二个为可选项配置, 第三个为回调函数

fs.mkdir(path.resolve(__dirname, "./test"), { recursive: true }, (err) => {
  if (err) {
    console.log(err);
  } else {
    console.log("创建成功");
  }
});
  • mkdirSync // 同步创建文件夹
mkdirSync(path.resolve(__dirname, "./test1"), { recursive: true });
  • fs.readdir(path[, options], callback)

    读取当前文件所在文件夹下的文件目录数组

    三个参数:第一个为文件夹路径,第二个可选项配置, 第三个为回调函数

readdir(path.resolve(__dirname, "./"), (err, data) => {
  if (err) {
    console.log(err);
  } else {
    console.log(data);
  }
});
 
// 打印值
[
  'node_modules',
  'package-lock.json',
  'package.json',
  'readFile.js',
  'test',
  'test1',
  '观书有感.txt'
]
  • fs.rmdir(path[, options], callback)

    options 的取值

    • maxRetries  如果遇到 EBUSYEMFILEENFILEENOTEMPTY 或 EPERM 错误,Node.js 将在每次尝试时以 retryDelay 毫秒的线性退避等待时间重试该操作。此选项表示重试次数。如果 recursive 选项不为 true,则忽略此选项。默认值:0
    • recursive  如果为 true,则执行递归目录删除。在递归模式下,操作将在失败时重试。默认值:false。已弃用。
    • retryDelay  重试之间等待的时间(以毫秒为单位)。如果 recursive 选项不为 true,则忽略此选项。默认值:100
rmdir(path.resolve(__dirname, "./test"), (err) => {
  if (err) {
    console.log(err);
  } else {
    console.log("删除成功");
  }
});
  • fs.rm(path[, options], callback)

    options 的取值

    • maxRetries  如果遇到 EBUSYEMFILEENFILEENOTEMPTY 或 EPERM 错误,Node.js 将在每次尝试时以 retryDelay 毫秒的线性退避等待时间重试该操作。此选项表示重试次数。如果 recursive 选项不为 true,则忽略此选项。默认值:0
    • recursive  如果为 true,则执行递归目录删除。在递归模式下,操作将在失败时重试。默认值:false
    • retryDelay  重试之间等待的时间(以毫秒为单位)。如果 recursive 选项不为 true,则忽略此选项。默认值:100
rm(path.resolve(__dirname, "./test"), { recursive: true }, (err) => {
  if (err) {
    console.log(err);
  } else {
    console.log("删除成功");
  }
});
  • fs.rmSync(path[, options])
  • options 

    • force  当为 true 时,如果 path 不存在,则异常将被忽略。默认值:false
    • maxRetries  如果遇到 EBUSYEMFILEENFILEENOTEMPTY 或 EPERM 错误,Node.js 将在每次尝试时以 retryDelay 毫秒的线性退避等待时间重试该操作。此选项表示重试次数。如果 recursive 选项不为 true,则忽略此选项。默认值:0
    • recursive  如果为 true,则执行递归目录删除。在递归模式下,操作将在失败时重试。默认值:false
    • retryDelay  重试之间等待的时间(以毫秒为单位)。如果 recursive 选项不为 true,则忽略此选项。默认值:100
    rmSync(path.resolve(__dirname, "./test"), { recursive: true });
        
    

    文件移动和重命名

    使用 rename 和 renameSync 来移动和重命名文件夹或文件

    fs.rename(oldPath, newPath, callback)
    fs.renameSync(oldPath, newPath)

    文件删除

    fs.unlink(path, callback)
    unlink(path.resolve(__dirname, "./观书有感.txt"), (err) => {
      if (err) {
        console.log(err);
      } else {
        console.log("删除成功");
      }
    });
    
    fs.unlinkSync(path)
    unlinkSync(path.resolve(__dirname, "./观书有感.txt"));
    
    fs.rm(path[, options], callback)
    rm(path.resolve(__dirname, "./test"), { recursive: true }, (err) => {
      if (err) {
        console.log(err);
      } else {
        console.log("删除成功");
      }
    });
    
    fs.rmSync(path[, options])
    rmSync(path.resolve(__dirname, "./test"), { recursive: true });
        
    

    注意:unlink 不能用来删除文件, rm 可以删除文件和文件夹

    文件移动和重命名

    使用 rename 和 renameSync 来移动和重命名文件夹或文件

    fs.rename(oldPath, newPath, callback)
    // 进行重命名
    rename(
      path.resolve(__dirname, "./观书有感.txt"),
      path.resolve(__dirname, "./观书有感2.txt"),
      (err) => {
        if (err) {
          console.log(err);
        } else {
          console.log("重命名成功");
        }
      }
    );
    
    // 移动文件夹
    rename(
      path.resolve(__dirname, "./观书有感2.txt"),
      path.resolve(__dirname, "./test1/观书有感2.txt"),
      (err) => {
        if (err) {
          console.log(err);
        } else {
          console.log("重命名成功");
        }
      }
    );
    
    fs.renameSync(oldPath, newPath)
    renameSync(
      path.resolve(__dirname, "./test1/观书有感2.txt"),
      path.resolve(__dirname, "./观书有感.txt")
    );
    
    

    查看文件状态

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

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

    • 可以获取文件状态

      stat(path.resolve(__dirname, "./观书有感.txt"), (err, data) => {
        if (err) {
          console.log(err);
        } else {
          console.log(data);
        }
      });
          
      // 打印值
      Stats {
        dev: 16777232,
        mode: 33188,
        nlink: 1,
        uid: 501,
        gid: 20,
        rdev: 0,
        blksize: 4096,
        ino: 86038321,
        size: 0,
        blocks: 0,
        atimeMs: 1756725548336.7957,
        mtimeMs: 1756725548336.7957,
        ctimeMs: 1756725548336.7957,
        birthtimeMs: 1756725548336.7957,
        atime: 2025-09-01T11:19:08.337Z,
        mtime: 2025-09-01T11:19:08.337Z,
        ctime: 2025-09-01T11:19:08.337Z,
        birthtime: 2025-09-01T11:19:08.337Z
      }