
欢迎来到 Node.js 核心模块的深度探索!
在 Node.js 的世界中,文件系统(File System,简称 fs
)模块无疑是处理 I/O 操作的基石。它赋予了 JavaScript 在服务器端直接与文件进行交互的能力,实现高效的文件读取、写入、修改、删除等功能。掌握 fs
模块,是构建任何 Node.js 应用,无论是 API 服务器还是命令行工具(CLI),都不可或缺的基础技能。
本节我们将重点讲解 fs
模块中常用的异步、基于 Promise 的 API ,配合 async/await
,让你能以最清晰、最具可读性的方式来管理文件操作。
一、fs 模块常用 API(Promise 方式,推荐实践)
Node.js 从 v10.0.0 版本开始,提供了 fs/promises
模块,实现了 fs
模块所有方法的 Promise 封装。这是目前官方推荐的文件操作方式,其核心优势在于:
- 语法清晰:告别回调地狱,代码逻辑更接近同步。
- 可读性强:流程控制直观,易于理解。
- 错误处理简洁 :可统一使用
try...catch
捕获所有异步异常。 - 流程控制:完美支持异步代码的执行顺序控制。
我们首先定义一个用于演示的 JSON 数据结构,模拟 AI 提示词库:
javascript
// 定义提示词数组
const prompts = [
{ title: '文章摘要', prompt: '请将以下文章内容提炼成简洁摘要,控制在100字以内:' },
{ title: '代码解释', prompt: '请解释下面这段 JavaScript 代码的作用,并指出潜在问题:' },
{ title: 'SEO优化建议', prompt: '请根据以下产品描述,生成3条SEO优化建议:' },
];
接下来,通过代码案例演示如何使用 fs/promises
来实现文件的 CRUD(创建、读取、更新、删除)操作。
1. ✅ 写入文件内容(writeFile)
fs.writeFile(path, data[, options])
用于向指定文件写入内容。如果文件不存在,则会创建新文件;如果文件已存在,其内容将被覆盖。
javascript
const fs = require('fs/promises');
// 写入文件内容
const writeFileExample = async () => {
try {
// 将 prompts 数组转换为格式化的 JSON 字符串
const jsonContent = JSON.stringify(prompts, null, 2);
// 写入文件,使用 'utf8' 编码
await fs.writeFile('./prompts.json', jsonContent, 'utf8');
console.log('提示词写入成功');
} catch (err) {
console.error('写入失败:', err);
}
}
writeFileExample();
关键点解析:
JSON.stringify(..., null, 2)
:以 2 个空格的缩进格式化 JSON 输出,提高可读性。'utf8'
:指定文件编码,确保文本内容的正确存储和读取。try...catch
:标准错误处理机制,防止 I/O 异常导致程序崩溃。
2. ✅ 读取文件内容(readFile)
fs.readFile(path[, options])
用于完整读取文件内容。
javascript
const fs = require('fs/promises');
// 读取文件内容
const readFileExample = async () => {
try {
// 读取文件内容,返回值为字符串(指定 'utf8' 编码)
const data = await fs.readFile('./prompts.json', 'utf8');
// 将 JSON 字符串转换回 JavaScript 对象
console.log('文件内容:', JSON.parse(data));
} catch (err) {
console.error('读取失败:', err);
}
}
readFileExample();
关键点解析:
- 编码的重要性 :如果未指定编码(如
'utf8'
),fs.readFile()
返回的是原始的 Buffer 对象,适用于二进制文件或需要手动解码的场景。对于文本文件,推荐直接指定编码。 - 数据转换 :由于文件 I/O 传输的是字节流,对于 JSON 或其他结构化数据,需要通过
JSON.parse()
将其反序列化为 JavaScript 对象。
3. ✅ 修改文件:读取 → 修改 → 写入(推荐模式)
对于结构化数据(如 JSON 文件),最佳实践是遵循 "读-改-写" 的流程,而不是简单地使用 fs.appendFile
(直接追加内容,会破坏 JSON 格式)。
javascript
const fs = require('fs/promises');
// 修改文件:读 → 改 → 写
const updateFileExample = async () => {
try {
// 第一步:读取原始 JSON 内容
const originalData = await fs.readFile('./prompts.json', 'utf-8');
// 第二步:解析原始 JSON 内容
const originalPrompts = JSON.parse(originalData);
// 第三步:在内存中修改数据(添加新提示词)
originalPrompts.push({ title: '新提示词', prompt: '这是一个全新的自定义提示词' });
// 第四步:将修改后的内容序列化并写回文件(覆盖原文件)
await fs.writeFile('./prompts.json', JSON.stringify(originalPrompts, null, 2), 'utf-8');
console.log('文件已成功修改');
} catch (error) {
console.error('文件修改失败:', error);
}
}
updateFileExample();
4. ✅ 删除文件(unlink)
fs.unlink(path)
用于删除指定路径的文件。这是一个不可逆的操作,应谨慎使用。
javascript
const fs = require('fs/promises');
// 删除文件
const deleteFileExample = async () => {
try {
await fs.unlink('./prompts.json');
console.log('文件删除成功');
} catch (err) {
// EBUSY(文件被占用)或 ENOENT(文件不存在)等错误应在此捕获
console.error('删除失败:', err);
}
}
deleteFileExample();
关键点解析:
unlink
:是文件删除的标准 UNIX 风格名称。- 错误捕获 :如果尝试删除一个不存在的文件,
fs.unlink()
会抛出ENOENT
(Error NO ENTry) 错误,必须通过try...catch
妥善处理。
5. ✅ 获取文件信息(stat)
fs.stat(path)
用于获取文件或目录的元数据,返回一个 Stats
对象。这是进行文件类型判断、权限检查或获取时间戳的关键。
javascript
const fs = require('fs/promises');
// 获取文件信息
const getFileInfoExample = async () => {
try {
const stats = await fs.stat('./prompts.json');
console.log('文件元信息:', {
size: stats.size, // 文件大小(字节)
创建时间: stats.birthtime,
修改时间: stats.mtime,
是否为文件: stats.isFile(),
是否为目录: stats.isDirectory(),
});
} catch (err) {
console.error('获取信息失败:', err);
}
}
getFileInfoExample();
关键点解析:
stats
对象:包含了文件的各种属性,如大小 (size
)、创建/修改时间 (birthtime
/mtime
)。isFile()
/isDirectory()
:用于判断文件系统的类型,是实现文件遍历或特定操作前的预检手段。
6. ✅ 读取目录内容(readdir)
fs.readdir(path)
用于读取指定目录下的所有文件和子目录的名称。
javascript
const fs = require('fs/promises');
// 读取目录内容
const readDirExample = async () => {
try {
// 读取当前目录('./')下的内容
const files = await fs.readdir('./');
console.log('当前目录内容:', files); // files 是一个字符串数组
} catch (err) {
console.error('读取目录失败:', err);
}
}
readDirExample();
关键点解析:
fs.readdir()
返回一个字符串数组,仅包含文件名或目录名,不包含路径信息 。若需获取完整路径,需要结合path
模块进行拼接。- 是实现文件查找、目录遍历等功能的基础 API。
💡 总结与实践建议
通过本节课的学习,我们已经系统掌握了 Node.js fs
模块的核心和推荐用法:
核心 API 总结
功能分类 | Promise API (推荐) | 作用描述 | 关键点 |
---|---|---|---|
创建/写入 | fs.writeFile |
写入内容到文件,覆盖原有内容或创建文件。 | 建议指定编码(如 'utf8' ),配合 JSON.stringify 写入结构化数据。 |
读取 | fs.readFile |
完整读取文件内容。 | 文本文件需指定编码(如 'utf8' ),否则返回 Buffer。配合 JSON.parse 读取结构化数据。 |
删除 | fs.unlink |
删除指定路径的文件。 | UNIX 风格名称,操作不可逆,需谨慎并捕获 ENOENT 错误。 |
元数据 | fs.stat |
获取文件或目录的详细信息(大小、时间戳等)。 | 返回 Stats 对象,通过 isFile() / isDirectory() 进行类型判断。 |
目录读取 | fs.readdir |
读取目录下的所有文件和目录名称。 | 返回字符串数组,不包含路径信息,是目录遍历的基础。 |
实践建议
- 首选 Promise API :使用
require('fs/promises')
结合async/await
,以实现代码的同步逻辑和清晰的错误处理。 - 核心文件操作 :熟练运用
writeFile
(写入/覆盖)、readFile
(读取)、unlink
(删除)、stat
(获取元数据) 和readdir
(读取目录)。 - 结构化数据操作模式:对于 JSON 等数据,请采用**"读取 → 解析 → 修改 → 序列化 → 写入"**的流程,保证数据完整性。
- 健壮性 :始终使用
try...catch
结构来封装文件操作,因为 I/O 操作中,权限不足、文件不存在等异常随时可能发生。
掌握了 fs
模块,你就拥有了在 Node.js 环境下高效、可靠地管理文件系统的完整能力。现在,尝试将这些 API 整合到你的项目中,开始构建更强大的后端应用吧!
多模态Ai项目全流程开发中,从需求分析,到Ui设计,前后端开发,部署上线,感兴趣打开链接(带项目功能演示) ,多模态AI项目开发中...