Node.js 的内置模块 fs(File System,文件系统)提供了操作系统文件的核心能力。通过 fs 模块,你可以完成文件的读写、创建、删除、重命名,以及目录的创建、遍历、删除等操作。 该模块内置在 Node.js 中,无需额外安装,同时支持异步回调、同步阻塞、Promise 三种调用方式,是 Node.js 服务端开发中处理文件的核心模块。
node 命令可以在终端中直接执行 JavaScript 文件。
创建一个 JavaScript 文件,如 hello-world.js,编写代码:
console.log('Hello Node.js!')打开终端,进入文件所在目录,执行命令:
node hello-world.js执行成功后,终端会输出对应的打印内容。
在项目根目录的 package.json 中添加配置,启用 ES Module 规范:
{
"type": "module"
}核心固定代码:ES Module 中无默认 __dirname,所有文件操作必须先定义(全局复用):
import { fileURLToPath } from 'url';
import { dirname } from 'path';
// 获取当前文件的绝对路径
const __filename = fileURLToPath(import.meta.url);
// 获取当前文件所在目录的绝对路径
const __dirname = dirname(__filename);// 导入 fs 文件系统模块
import fs from 'fs';
// 导入 path 路径模块(用于安全拼接路径)
import path from 'path';
// 固定:定义 __dirname
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);直接拼接路径容易出现跨系统错误(Windows \ / Mac/Linux /),必须使用 path.join() 拼接:
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
// 跨系统兼容的安全路径
const filePath = path.join(__dirname, 'files', 'test.txt');import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const filePath = path.join(__dirname, 'files', 'test.txt');
// 异步读取:错误优先回调
fs.readFile(filePath, 'utf8', (err, data) => {
if (err) {
console.error('文件读取失败:', err);
return;
}
console.log('文件内容:', data);
});import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const filePath = path.join(__dirname, 'files', 'test.txt');
// 同步读取:try/catch 捕获异常
try {
const data = fs.readFileSync(filePath, 'utf8');
console.log('文件内容:', data);
} catch (err) {
console.error('文件读取失败:', err);
}import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const filePath = path.join(__dirname, 'files', 'test1.txt');
// 覆盖写入文件
fs.writeFile(filePath, 'Hello my first node.js', 'utf8', err => {
if (err) {
console.error('文件写入失败:', err);
} else {
console.log('文件写入成功');
}
});// 基于上方代码,追加内容
fs.writeFile(filePath, '\n追加的内容', { encoding: 'utf8', flag: 'a' }, err => {
if (!err) console.log('追加成功');
});import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import { dirname } from 'path';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const dirPath = path.join(__dirname, 'my-folder');
// 1. 递归创建多级目录
fs.mkdir(dirPath, { recursive: true }, err => {
if (!err) console.log('目录创建成功');
});
// 2. 读取目录内容
fs.readdir(__dirname, (err, files) => {
console.log('当前目录文件:', files);
});
// 3. 重命名文件/目录
fs.rename(dirPath, path.join(__dirname, 'new-folder'), () => {});
// 4. 删除文件
fs.unlink(path.join(__dirname, 'test.txt'), () => {});
// 5. 删除空目录
fs.rmdir(dirPath, () => {});ES6 语法,简化 fs 回调函数代码,是文件操作的标准写法。
// 无参数
const func1 = () => {}
// 单个参数(可省略括号)
const func2 = param => {}
// 多个参数
const func3 = (param1, param2) => {}
// 单行返回值(省略 return 和大括号)
const add = (a, b) => a + b语法简洁:大幅缩短回调函数代码
无独立 this:继承父作用域的 this
不能用作构造函数:无法使用 new 调用
无 arguments 对象
fs 模块的核心设计:异步非阻塞(Node.js 精髓),同步方法仅适合简单场景。
文件操作的本质是 IO(输入 / 输出),根据阻塞特性和实现方式,分为三大经典模型,直接对应 Node.js fs 模块的不同用法:
定义:发起 IO 操作后,程序完全阻塞等待,直到 IO 完成才能执行后续代码
对应 Node.js 方法:fs.readFileSync / fs.writeFileSync 等同步方法
特点:单线程下会卡住整个程序,效率低
场景:简单脚本、初始化配置、测试代码
定义:发起 IO 操作后,程序不阻塞,可以继续执行其他任务;轮询 / 事件监听 IO 完成状态
对应 Node.js 方法:fs.readFile / fs.writeFile 等异步回调方法
特点:基于事件循环,高性能;回调嵌套过多会产生「回调地狱」
场景:服务端常规文件操作
定义:发起 IO 操作后,程序无需等待、无需轮询;操作系统完成 IO 后主动通知程序
对应 Node.js 方法:fs/promises + async/await
特点:最优雅的异步模型,无阻塞、无回调地狱、代码可读性极高
场景:生产环境、大型项目(官方最优方案)