在服务端开发中,文件操作是不可避免的需求。无论是读取配置、写入日志、上传文件、管理缓存,还是处理图片和文档,都离不开文件系统操作。Node.js 通过内置的 fs 模块提供了一整套文件读写能力,使 JavaScript 能够高效地与操作系统文件系统交互。
一、fs 模块概述
fs 模块是 Node.js 的核心模块之一,用于访问本地文件系统。它提供了文件读取、写入、创建、删除、复制、重命名、目录管理等一整套能力。
在 Node.js 中,fs 不需要安装,直接通过以下方式引入即可使用:
js
const fs = require('fs')
从 Node.js 10 之后,fs 模块同时支持回调方式、Promise 方式以及同步方式,开发者可以根据场景灵活选择。
二、三种使用方式对比
1. 回调方式
这是最早期的使用形式,通过回调函数处理结果:
js
fs.readFile('a.txt', 'utf8', (err, data) => {
if (err) throw err
console.log(data)
})
缺点是嵌套较多,代码可读性在复杂场景中会下降。
2. Promise 方式
Node.js 提供了 fs.promises 接口,更适合现代开发风格:
js
const fs = require('fs/promises')
async function read() {
const data = await fs.readFile('a.txt', 'utf8')
console.log(data)
}
这种方式可以结合 async / await 使用,可读性较好。
3. 同步方式
js
const data = fs.readFileSync('a.txt', 'utf8')
同步方式简单直接,但会阻塞进程,不适合高并发服务,仅适用于脚本或初始化阶段。
三、常用文件操作示例
1. 写入文件
js
fs.writeFile('log.txt', 'hello', err => {
if (err) console.error(err)
})
2. 判断文件是否存在
js
fs.access('a.txt', err => {
if (err) console.log('不存在')
})
3. 创建目录
js
fs.mkdir('logs', { recursive: true }, err => {})
4. 删除文件
js
fs.unlink('log.txt', err => {})
5. 读取目录
js
fs.readdir('./logs', (err, files) => {
console.log(files)
})
四、流式操作:处理大文件必备
当读取大文件时,如果一次性加载全部内容到内存,很容易导致内存暴涨。
Node.js 提供了流式接口:
js
const readStream = fs.createReadStream('big.txt')
const writeStream = fs.createWriteStream('copy.txt')
readStream.pipe(writeStream)
这种方式可以边读边写,适合处理视频、压缩包等大文件。
五、文件监听与变更监控
fs 还支持监听文件变化:
js
fs.watch('config.json', () => {
console.log('文件发生变化')
})
该功能在热加载、配置动态更新中非常有用。
六、路径问题与跨平台兼容
配合 path 模块可避免路径问题:
js
const path = require('path')
const filePath = path.join(__dirname, 'a.txt')
避免硬编码路径,有助于兼容不同操作系统。
七、常见坑点总结
文件编码未指定,导致中文乱码。 忘记处理异常,程序意外崩溃。 同步 API 用在 Web 服务中,导致阻塞。 路径拼接写死,引发跨平台问题。 大文件用 readFile 直接读入内存。
八、总结
fs 模块是 Node.js 与操作系统交互的基础能力。 小文件用 Promise API。 大文件使用流处理。 服务环境避免阻塞式操作。 涉及路径务必结合 path。
掌握 fs 模块,是迈向 Node.js 后端开发的重要一步。