Skip to content

NodeJS中的fs模块

fs 模块简介

fs 全称为 fileSystem(文件系统),是 Node.js 中,可以操作计算机中的文件,文件操作是服务器的基本能力之一。

文件写入

异步写入

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

  • 返回值:undefined
  • 代码示例:
js
// require 是 Node 中的内置函数,用来导入模块
const fs = require("fs");

fs.writeFile("./暴富指南.txt", "从事IT行业,狠狠赚一笔!", (err) => {
  // err是回调参数,若写入成功值为null,若写入失败值为错误对象
  if (err) {
    console.log("写入失败,原因:" + err);
  } else {
    console.log("写入成功");
  }
});

可选配置说明:

js
const fs = require("fs");

fs.writeFile(
  "./暴富指南.txt",
  "从事IT行业,狠狠赚一笔!\n",
  /* 
  encoding配置文件编码,例如:uft8、ascii、base64 等等,默认值为:utf8。
  flag用于配置文件操作,例如:w(写入模式)、a(追加模式) 等等,默认值为:w。
  mode用于设置文件权限,例如:0o666(可读可写)、0o444(只读),默认值为:0o666。
*/
  { encoding: "utf8", flag: "w", mode: 0o444 },
  (err) => {
    if (err) {
      console.log("写入失败,原因:" + err);
    } else {
      console.log("写入成功");
    }
  }
);

思考:

我们完全可以通过鼠标操作来创建文件,为什么还要用代码进行操作呢?

同步写入

语法:fs.writeFileSync(file, data[, options]),无需传入回调函数

  • 返回值:undefined
  • 代码示例:
js
const fs = require("fs");

try {
  // 同步写入文件
  fs.writeFileSync("./暴富指南.txt", "从事IT行业,狠狠赚一笔!");
  console.log("文件写入成功");
} catch (error) {
  console.log("文件写入失败", error);
}

与异步写入对比:

  • 异步写入
js
const fs = require("fs");
// 异步写入
console.log("==开始==");
fs.writeFile("./暴富指南.txt", "从事IT行业,狠狠赚一笔!", (err) => {
  if (err) {
    console.log("写入失败,原因:" + err);
  } else {
    console.log("写入成功");
  }
});
console.log("==结束==");
  • 同步写入
js
const fs = require("fs");
// 异步写入
console.log("==开始==");
try {
  fs.writeFileSync("./暴富指南.txt", "从事IT行业,狠狠赚一笔!");
  console.log("写入成功");
} catch (error) {
  console.log("写入失败", err);
}
console.log("==结束==");

输出结果如下

==开始==
写入成功
==结束==

使用原则:

  • 若想要其他任务不被文件写入操作所阻塞,或要优化性能,则使用异步的 writeFile 方法。
  • 若想要其他任务执行时确保文件写入完成,则使用同步的 writeFileSync 方法。

文件读取

异步读取

  • 语法:fs.readFile(path[, options], callback)
  • 返回值:undefined
  • 代码示例(不指定字符编码):
js
const fs = require("fs");

// err是错误信息,data是读取出来的数据
fs.readFile("./暴富指南.txt", (err, data) => {
  if (err) throw err;
  // 在读取时,若不指定字符编码,则data的值是一个Buffer对象
  console.log(data); // 输出的是Buffer对象
});
  • 代码示例(指定字符编码)
js
const fs = require("fs");

// err是错误信息,data是读取出来的数据
fs.readFile("./暴富指南.txt", { encoding: "utf8" }, (err, data) => {
  if (err) throw err;
  // 在读取时,若指定字符编码,则data的值是指定字符编码的内容
  console.log(data); // 输出的是utf8编码的文本内容
});

对 Buffer 的理解

为什么要有 Buffer? Node.js 最初的定位就是服务器端解决方案,所以它需要高效地处理:网络处理、文件操作等等,而这些都涉及到对二进制数据的处理,因此在 Node.js 中引入了一个全局的 Buffer 类,用于直接操作内存中的二进制数据Buffer 中的数据表示 当使用 fs 模块相关 API 取文件时,若不指定字符编码,文件内容会以二进制数据读取到 Buffer 中,以字符串"hello"为例,它在 utf8 编码下的二进制表示如下(为了使呈现的内容更加便于观察,Buffer 在打印时,将二进制转换为了十六进制):

  • h=====> 01101000(二进制) =====> 68(十六进制)
  • e=====> 01100101(二进制) =====> 65(十六进制)
  • l=====> 01101100(二进制) =====> 6c(十六进制)
  • l=====> 01101100(二进制) =====> 6c(十六进制)
  • o=====> 01101111(二进制) =====> 6f(十六进制)

所以我们看到的输出是:<Buffer 68 65 6c 6c 6f>Buffer 的常用方法 在 Node 中手动创建 Buffer 数据,有三种方式: 方式一:Buffer.from()

js
const bf1 = Buffer.from("hello");
console.log(bf1); // 输出: <Buffer 68 65 6c 6c 6f>

方式二:Buffer.alloc()

js
// Buffer.alloc()是创建固定大小Buffer的推荐方式
const bf2 = Buffer.alloc(5); // 创建一个长度为5的Buffer,初始化为0
console.log(bf2); // 输出: <Buffer 00 00 00 00 00>

bf2.write("hello");
console.log(bf2); // 输出: <Buffer 68 65 6c 6c 6f>

方式三:Buffer.allocUnsafe()

js
const bf3 = Buffer.allocUnsafe(5);
bf3.write("hello");
console.log(bf3); // 输出: <Buffer 68 65 6c 6c 6f>

// 测试allocUnsafe分配内存中包含旧数据
const bf01 = Buffer.allocUnsafe(8000);
console.log(bf01[500]); //输出的很可能不是0

const bf02 = Buffer.allocUnsafe(8000);
console.log(bf02[500]); //输出的很可能不是0

const bf03 = Buffer.allocUnsafe(8000);
console.log(bf03[500]); //输出的很可能不是0

注意:

实际开发中我们很少使用上述方法手动创建 Buffer 存储数据,通常都是我们的一些操作 Node 底层给我们返回 Buffer 数据,例如:文件读取、网络请求等等。

同步读取

语法:fs.readFileSync(path[, options])

  • 返回值: string | Buffer
  • 代码示例:
js
const fs = require("fs");

let data1 = fs.readFileSync("./暴富指南.txt");
let data2 = fs.readFileSync("./暴富指南.txt", "utf-8");

console.log(data1.toString()); // hello
console.log(data2); // hello

路径的说明

相对路径写法如下:

写法含义
./a.txt当前目录下的 a.txt
a.txt等价于上面的写法
../a.txt当前目录的上一级目录中的 a.txt

绝对路径写法如下:

写法含义
D:/test/demowindows 系统下的绝对路径
/usr/binLinux 系统下的绝对路径。
在 windows 下也可以这样写,不过/指向当前磁盘的根目录

注意:

  1. 相对路径相对的是命令行执行的位置(工作目录),而并非是文件的所在位置。
  2. 所以当命令执行的目录,与文件所在目录不一致时,会出现一些 BUG。

path 与__dirname

__dirname 是 Node.js 环境中的内置变量, 获取到的是当前执行脚本所在的目录的绝对路径,无需任何特殊声明就可以直接使用: 代码示例:

js
let data = fs.writeFileSync(__dirname + "/a.txt");

也可以借助内置的 path 模块进行更好的处理:

js
const path = require("path");
let writePath = path.resolve(__dirname, "./a.txt");
fs.writeFileSync(writePath);

注意:

fs 模块的时候,尽量使用 将路径转化为绝对路径,这样可以避免相对路径产生的 Bug。