1、fs模块是什么
Node.js 中的 fs 模块(File System 模块)是用于与文件系统交互的核心模块,提供了读取、写入、删除、修改文件
及目录等操作的 API,支持同步和异步
两种调用方式。
2、如何导入fs模块
// 方式1:CommonJS 规范(Node.js 默认)
const fs = require('fs');
// 方式2:ES 模块规范(需在 package.json 中设置 "type": "module")
import fs from 'fs';
3、fs模块的常用方法
方法 | 描述 | 类型 |
---|---|---|
fs.readFile(path, callback) | 读取文件内容 | 异步 |
fs.readFileSync(path) | 读取文件内容 | 同步 |
fs.writeFile(path, data, callback) | 写入内容到文件(覆盖原有内容) | 异步 |
fs.writeFileSync(path, data) | 写入内容到文件(覆盖原有内容) | 同步 |
fs.appendFile(path, data, callback) | 追加内容到文件 | 异步 |
fs.appendFileSync(path, data) | 追加内容到文件 | 同步 |
fs.unlink(path, callback) | 删除文件 | 异步 |
fs.unlinkSync(path) | 删除文件 | 同步 |
fs.mkdir(path, callback) | 创建目录 | 异步 |
fs.mkdirSync(path) | 创建目录 | 同步 |
fs.rmdir(path, callback) | 删除空目录 | 异步 |
fs.rmdirSync(path) | 删除空目录 | 同步 |
fs.readdir(path, callback) | 读取目录中的文件和子目录列表 | 异步 |
fs.readdirSync(path) | 读取目录中的文件和子目录列表 | 同步 |
fs.stat(path, callback) | 获取文件 / 目录的详细信息 | 异步 |
fs.statSync(path) | 获取文件 / 目录的详细信息 | 同步 |
3-1读取文件
- 异步:
fs.readFile(path[, encoding], callback)
接收文件路径、编码格式(可选,默认 Buffer)和回调函数,回调参数为错误信息和文件内容。 - 同步:
fs.readFileSync(path[, encoding])
直接返回文件内容,需用 try/catch 捕获错误。
// 异步
fs.readFile('file.txt', 'utf8', (err, data) => {
if (err) throw err;
console.log(data);
});
// 同步
try {
const data = fs.readFileSync('file.txt', 'utf8');
console.log(data);
} catch (err) {
console.error(err);
}
// 2-3 读取文件夹
fs.readdir('../文件夹 ', (err, data) => {
if (err) {
console.log('读取失败');
return;
}
console.log(data);
});
流式读取
流式读取是 Node.js 中高效处理文件(尤其是大文件)的方式,它将文件内容分割成小块(chunk),逐块读取并处理,而非一次性将整个文件加载到内存。 核心特点:
- 内存高效:无需一次性加载全部内容,适合 GB 级大文件,避免内存溢出
- 实时处理:读取到部分数据即可立即处理,无需等待完整文件加载
- 事件驱动:通过
data
事件获取数据块,end
事件标识读取完成
const fs = require('fs');
const readStream = fs.createReadStream('large-file.txt');
// 每收到一块数据(trunk)就触发
readStream.on('data', (chunk) => {
console.log('收到数据块:', chunk.toString());
});
// 全部读取完成触发
readStream.on('end', () => {
console.log('读取完毕');
});
// 发生错误时触发
readStream.on('error', (err) => {
console.error('读取错误:', err);
});
文件读取的常见场景
- 配置加载:应用启动时读配置文件(如 JSON、YAML),获取端口、数据库连接等运行参数;
- 数据导入:从 CSV、Excel 或备份文件中读数据,用于分析、数据库恢复等;
- 内容交互:文本编辑器读文件展示内容、媒体播放器读文件加载音视频;
- 日志分析:读日志文件排查故障、分析系统运行 / 用户行为;
- 代码 / 脚本执行:解释器 / 编译器读源码文件,执行脚本或编译生成程序;
- 大数据处理:分块读海量数据文件,避免内存不足(如分布式计算场景)。
3-2写入文件
- 异步:
fs.writeFile(path, data[, options], callback)
将 data 写入指定文件(覆盖原有内容),完成后执行回调。 - 同步:
fs.writeFileSync(path, data[, options])
同步写入,同样覆盖原有内容,需处理可能的错误。
// 异步
fs.writeFile('file.txt', 'Hello World', (err) => {
if (err) throw err;
console.log('文件已写入');
});
// 同步
try {
fs.writeFileSync('file.txt', 'Hello World');
console.log('文件已写入');
} catch (err) {
console.error(err);
}
流式写入
在 Node.js 中,流式写入(Stream Writing)是处理大文件或持续数据写入的高效方式,它可以分块处理数据,避免一次性加载大量数据到内存中。
关键方法和事件:
fs.createWriteStream(path[, options])
:创建写入流writeStream.write(chunk[, encoding][, callback])
:写入数据块writeStream.end([chunk][, encoding][, callback])
:结束写入流'drain'
事件:当内部缓冲区被清空时触发,此时可以继续写入'finish'
事件:所有数据已被写入底层系统时触发'error'
事件:发生错误时触发
// 示例
const fs = require('fs');//导入 Node.js 内置的 `fs` 模块
let ws = fs.createWriteStream('./观书有感.txt');
//调用 `fs.createWriteStream()` 方法创建一个可写流(WriteStream),用于向指定文件写入数据。
//'./观书有感.txt'` 是目标文件路径(当前目录下的 `观书有感.txt`),如果文件不存在会自动创建。
//变量 `ws` 存储这个可写流对象,后续通过它进行写入操作。
ws.write('111\r\n');
ws.write('222\r\n');
ws.write('333\r\n');
ws.write('444\r\n');
ws.end();
//调用 `end()` 方法结束写入流,表明所有数据已写入完成。
文件写入的常见场景:
- 日志记录:服务器、应用程序将操作、错误、访问等日志信息写入文件,用于后续分析和排查问题。
- 数据持久化:把内存中的数据(如文档内容、应用配置等)长期保存到文件,以便后续读取和使用。
- 数据导出:将应用程序或数据库中的数据,以特定格式(如 CSV、Excel、PDF 等)导出为文件,用于数据迁移或分享。
- 动态内容生成:根据不同逻辑(如 Web 请求、模板渲染等)动态生成内容并写入文件,像静态网站生成、代码自动生成等场景。
- 大数据处理:处理海量数据时,分块将数据或处理结果写入文件,避免内存不足,如大规模数据分析、数据清洗等场景。
3-3追加文件
- 异步:
fs.appendFile(path, data[, options], callback)
在文件末尾添加内容(不覆盖原有内容),适合日志记录等场景。 - 同步:
fs.appendFileSync(path, data[, options])
同步追加,功能与异步版本一致。
// 异步
fs.appendFile('file.txt', '追加内容', (err) => {
if (err) throw err;
console.log('内容已追加');
});
// 同步
try {
fs.appendFileSync('file.txt', '追加内容');
console.log('内容已追加');
} catch (err) {
console.error(err);
}
//另外fs.writeFile也可以实现追加效果,只需要增加一个配置对象{flag:a}
//w = 写入模式,a = 追加模式,r = 读取模式
fs.writeFile('file.txt', '111', {flag:a},(err) => {
if (err) throw err;
console.log('写入成功');
});
3-4 删除文件
- 异步:
fs.unlink(path, callback)
删除指定文件,删除成功后执行回调。 - 同步:
fs.unlinkSync(path)
同步删除文件,无返回值,错误需通过 try/catch 处理。
// 异步
fs.unlink('file.txt', (err) => {
if (err) throw err;
console.log('文件已删除');
});
// 同步
try {
fs.unlinkSync('file.txt');
console.log('文件已删除');
} catch (err) {
console.error(err);
}
- 异步:
fs.rm(path, options, callback)
删除指定文件或目录,删除成功后执行回调。支持通过options
配置递归删除(recursive: true
)等行为。 - 同步:
fs.rmSync(path, options)
同步删除文件或目录,无返回值,错误需通过try/catch
处理。可通过options
配置递归删除等行为。
// 异步
fs.rm('./论语.txt', { recursive: true }, (err) => {
if (err) {
console.log('删除失败~');
return;
}
console.log('删除成功');
});
// 同步
try {
fs.rmSync('./论语.txt', { recursive: true });
console.log('删除成功');
} catch (err) {
console.error('删除失败~', err);
}
3-5 创建目录/文件夹
- 异步:
fs.mkdir(path[, options], callback)
创建单层目录,若目录已存在会报错(可通过 options 设置递归创建)。 - 同步:
fs.mkdirSync(path[, options])
同步创建目录,用法与异步版本对应。
// 异步
fs.mkdir('newdir', (err) => {
if (err) throw err;
console.log('目录已创建');
});
// 同步
try {
fs.mkdirSync('newdir');
console.log('目录已创建');
} catch (err) {
console.error(err);
}
// 递归创建 (加上{ recursive: true })
fs.mkdir('./a/b/c', { recursive: true }, err => {
if (err) { console.log('创建失败~');
return
; } console.log('创建成功'); });
{ recursive: true }
是 Node.js 文件操作中的一个配置选项:
-
用于
fs.mkdir()
时:自动创建路径中所有不存在的目录(如创建a/b/c
时,会自动创建a
和b
) -
用于
fs.rm()
时:递归删除目录及其所有子内容(包括非空目录)
简单说,就是「自动处理多层级结构」的意思。
3-6 读取目录
- 异步:
fs.readdir(path[, options], callback)
获取目录下所有文件 / 子目录名称数组,通过回调返回。 - 同步:
fs.readdirSync(path[, options])
同步返回目录内容列表。
// 异步
fs.readdir('dir', (err, files) => {
if (err) throw err;
console.log(files);
});
// 同步
try {
const files = fs.readdirSync('dir');
console.log(files);
} catch (err) {
console.error(err);
}
3-7获取文件信息
- 异步:
fs.stat(path, callback)
获取文件 / 目录的元数据(大小、类型、修改时间等),通过 stats 对象访问。 - 同步:
fs.statSync(path)
同步返回 stats 对象,可用于判断是文件(isFile ())还是目录(isDirectory ())。
// 异步
fs.stat('file.txt', (err, stats) => {
if (err) throw err;
console.log(stats.size); // 文件大小
console.log(stats.isFile()); // 是否为文件
});
// 同步
try {
const stats = fs.statSync('file.txt');
console.log(stats.mtime); // 最后修改时间
} catch (err) {
console.error(err);
}
3-8文件重命名
在 Node.js 中,文件重命名主要通过 fs
模块的 rename()
或 renameSync()
方法实现,可实现文件 / 目录的重命名或移动功能。
- 异步方式(推荐) :
const fs = require('fs');
fs.rename('旧文件名.txt', '新文件名.txt', (err) => {
if (err) throw err;
console.log('重命名成功');
});
- 同步方式:
const fs = require('fs');
try {
fs.renameSync('旧路径', '新路径');
console.log('重命名成功');
} catch (err) {
console.error(err);
}
3-9查看资源状态
在 Node.js 中,可通过fs
模块的多个方法查看资源状态,以下是具体介绍:
1. fs.stat()
与fs.statSync()
- 功能:
fs.stat()
是异步方法,fs.statSync()
是同步方法, 用于获取文件或目录的详细信息,像文件大小、创建时间、修改时间、访问时间、文件权限等。 - 示例
const fs = require('fs');
// 异步方式
fs.stat('example.txt', (err, stats) => {
if (err) {
console.error('获取状态失败:', err);
return;
}
console.log('文件大小:', stats.size);
console.log('创建时间:', stats.birthtime);
console.log('修改时间:', stats.mtime);
});
// 同步方式
try {
const stats = fs.statSync('example.txt');
console.log('文件大小:', stats.size);
console.log('创建时间:', stats.birthtime);
console.log('修改时间:', stats.mtime);
} catch (err) {
console.error('获取状态失败:', err);
}
2. fs.lstat()
与fs.lstatSync()
- 功能:和
fs.stat()
类似,区别在于,当目标是符号链接(软链接)时,fs.lstat()
返回的是符号链接本身的状态,而不是符号链接所指向的文件或目录的状态。 - 示例
const fs = require('fs');
// 异步方式
fs.lstat('symlink.txt', (err, stats) => {
if (err) {
console.error('获取符号链接状态失败:', err);
return;
}
console.log('符号链接大小:', stats.size);
});
// 同步方式
try {
const stats = fs.lstatSync('symlink.txt');
console.log('符号链接大小:', stats.size);
} catch (err) {
console.error('获取符号链接状态失败:', err);
}
3. fs.access()
与fs.accessSync()
- 功能:检查当前用户对文件或目录是否具有特定的访问权限,比如读权限、写权限、执行权限等。
- 示例
const fs = require('fs');
const { constants } = fs;
// 异步方式,检查是否有读和写权限
fs.access('test.txt', constants.R_OK | constants.W_OK, (err) => {
if (err) {
console.log('没有读或写权限');
return;
}
console.log('具有读和写权限');
});
// 同步方式
try {
fs.accessSync('test.txt', constants.R_OK | constants.W_OK);
console.log('具有读和写权限');
} catch (err) {
console.log('没有读或写权限');
}
4. fs.existsSync()
- 功能:同步检查文件或目录是否存在,返回布尔值。不过不推荐在异步操作场景中大量使用,因为会阻塞事件循环,影响程序性能。
- 示例
const fs = require('fs');
const exists = fs.existsSync('check.txt');
if (exists) {
console.log('文件存在');
} else {
console.log('文件不存在');
}