NodeJS中的fs模块
fs 模块简介
fs 全称为 fileSystem(文件系统),是 Node.js 中,可以操作计算机中的文件,文件操作是服务器的基本能力之一。
文件写入
异步写入
语法:fs.writeFile(file, data[, options], callback)
- 返回值:undefined
- 代码示例:
// require 是 Node 中的内置函数,用来导入模块
const fs = require("fs");
fs.writeFile("./暴富指南.txt", "从事IT行业,狠狠赚一笔!", (err) => {
// err是回调参数,若写入成功值为null,若写入失败值为错误对象
if (err) {
console.log("写入失败,原因:" + err);
} else {
console.log("写入成功");
}
});可选配置说明:
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
- 代码示例:
const fs = require("fs");
try {
// 同步写入文件
fs.writeFileSync("./暴富指南.txt", "从事IT行业,狠狠赚一笔!");
console.log("文件写入成功");
} catch (error) {
console.log("文件写入失败", error);
}与异步写入对比:
- 异步写入
const fs = require("fs");
// 异步写入
console.log("==开始==");
fs.writeFile("./暴富指南.txt", "从事IT行业,狠狠赚一笔!", (err) => {
if (err) {
console.log("写入失败,原因:" + err);
} else {
console.log("写入成功");
}
});
console.log("==结束==");- 同步写入
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
- 代码示例(不指定字符编码):
const fs = require("fs");
// err是错误信息,data是读取出来的数据
fs.readFile("./暴富指南.txt", (err, data) => {
if (err) throw err;
// 在读取时,若不指定字符编码,则data的值是一个Buffer对象
console.log(data); // 输出的是Buffer对象
});- 代码示例(指定字符编码)
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()
const bf1 = Buffer.from("hello");
console.log(bf1); // 输出: <Buffer 68 65 6c 6c 6f>方式二:Buffer.alloc()
// 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()
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
- 代码示例:
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/demo | windows 系统下的绝对路径 |
| /usr/bin | Linux 系统下的绝对路径。 |
| 在 windows 下也可以这样写,不过/指向当前磁盘的根目录 |
注意:
- 相对路径相对的是命令行执行的位置(工作目录),而并非是文件的所在位置。
- 所以当命令执行的目录,与文件所在目录不一致时,会出现一些 BUG。
path 与__dirname
__dirname 是 Node.js 环境中的内置变量, 获取到的是当前执行脚本所在的目录的绝对路径,无需任何特殊声明就可以直接使用: 代码示例:
let data = fs.writeFileSync(__dirname + "/a.txt");也可以借助内置的 path 模块进行更好的处理:
const path = require("path");
let writePath = path.resolve(__dirname, "./a.txt");
fs.writeFileSync(writePath);注意:
fs 模块的时候,尽量使用 将路径转化为绝对路径,这样可以避免相对路径产生的 Bug。

