1.3 fs模块详解

 fs 模块详解

Node.js 的 fs 模块提供了与文件系统交互的能力,是服务器端编程的核心模块之一。它支持同步、异步(回调式)和 Promise 三种 API 风格,可满足不同场景的需求。

1. 模块引入
const fs = require('fs');          // 回调式 API
const fsPromises = require('fs').promises; // Promise API
const fsSync = require('fs');      // 同步 API
2. 文件读取操作
异步回调方式
fs.readFile('example.txt', 'utf8', (err, data) => {
  if (err) {
    console.error('读取文件失败:', err);
    return;
  }
  console.log('文件内容:', data);
});
Promise 方式
fsPromises.readFile('example.txt', 'utf8')
  .then(data => console.log('文件内容:', data))
  .catch(err => console.error('读取文件失败:', err));

// 或使用 async/await
async function readFileAsync() {
  try {
    const data = await fsPromises.readFile('example.txt', 'utf8');
    console.log('文件内容:', data);
  } catch (err) {
    console.error('读取文件失败:', err);
  }
}
同步方式
try {
  const data = fsSync.readFileSync('example.txt', 'utf8');
  console.log('文件内容:', data);
} catch (err) {
  console.error('读取文件失败:', err);
}
3. 文件写入操作
覆盖写入
// 异步
fs.writeFile('output.txt', 'Hello World!', err => {
  if (err) console.error('写入失败:', err);
});

// Promise
fsPromises.writeFile('output.txt', 'Hello World!')
  .then(() => console.log('写入成功'))
  .catch(err => console.error('写入失败:', err));

// 同步
fsSync.writeFileSync('output.txt', 'Hello World!');
追加写入
fs.appendFile('log.txt', '追加内容\n', err => { /* ... */ });
fsPromises.appendFile('log.txt', '追加内容\n');
fsSync.appendFileSync('log.txt', '追加内容\n');
4. 文件和目录操作
创建目录
// 递归创建多级目录(如 mkdir -p)
fs.mkdir('dir/subdir', { recursive: true }, err => { /* ... */ });
fsPromises.mkdir('dir/subdir', { recursive: true });
fsSync.mkdirSync('dir/subdir', { recursive: true });
读取目录
fs.readdir('dir', (err, files) => {
  console.log('目录内容:', files); // 返回文件名数组
});
重命名 / 移动文件
fs.rename('old.txt', 'new.txt', err => { /* ... */ });
fsPromises.rename('old.txt', 'new.txt');
fsSync.renameSync('old.txt', 'new.txt');
删除文件 / 目录
// 删除文件
fs.unlink('file.txt', err => { /* ... */ });
fsPromises.unlink('file.txt');
fsSync.unlinkSync('file.txt');

// 删除目录(递归删除使用 { recursive: true })
fs.rmdir('dir', err => { /* ... */ });
fsPromises.rmdir('dir', { recursive: true });
fsSync.rmdirSync('dir', { recursive: true });
5. 文件状态检查
fs.stat('example.txt', (err, stats) => {
  if (err) return;
  
  console.log('是否为文件:', stats.isFile());
  console.log('是否为目录:', stats.isDirectory());
  console.log('文件大小:', stats.size, '字节');
  console.log('创建时间:', stats.ctime);
});

// Promise 版本
fsPromises.stat('example.txt').then(stats => { /* ... */ });
6. 流式操作

适合处理大文件,避免内存溢出:

读取流
const readStream = fs.createReadStream('large_file.txt', {
  encoding: 'utf8',
  highWaterMark: 1024 * 1024 // 1MB 缓冲区
});

readStream.on('data', chunk => {
  console.log('读取块:', chunk.length);
});

readStream.on('end', () => console.log('读取完成'));
readStream.on('error', err => console.error('读取错误:', err));
写入流
const writeStream = fs.createWriteStream('output.txt');

writeStream.write('第一部分内容');
writeStream.write('第二部分内容');
writeStream.end(); // 结束写入

writeStream.on('finish', () => console.log('写入完成'));
管道操作(高效复制文件)
const readStream = fs.createReadStream('input.txt');
const writeStream = fs.createWriteStream('output.txt');

readStream.pipe(writeStream); // 自动处理背压问题
7. 文件路径处理

通常配合 path 模块使用:

const path = require('path');

const filePath = '/home/user/dir/file.txt';
console.log('文件名:', path.basename(filePath)); // 'file.txt'
console.log('目录:', path.dirname(filePath));    // '/home/user/dir'
console.log('扩展名:', path.extname(filePath));  // '.txt'
console.log('绝对路径:', path.resolve('file.txt')); // 解析为绝对路径
8. 监听文件变化
// 监听文件或目录变化
fs.watch('dir', (eventType, filename) => {
  console.log(`文件 ${filename} 发生 ${eventType} 事件`);
});
9. 同步 vs 异步 vs Promise
类型适用场景特点
同步 API配置加载、脚本工具阻塞执行,可能导致性能问题
回调 API传统异步场景需处理回调地狱问题
Promise API现代异步代码(async/await)避免回调地狱,支持链式调用
10. 最佳实践
  1. 优先使用异步 API:Node.js 是单线程的,同步操作会阻塞整个事件循环。
  2. 错误处理:始终处理文件操作可能抛出的错误。
  3. 大文件处理:使用流 API 处理大文件,避免内存溢出。
  4. 路径安全:使用 path 模块处理路径,避免路径遍历攻击。
  5. Promise 化:若需使用回调 API,可用 util.promisify 转换为 Promise:
    const { promisify } = require('util');
    const readFile = promisify(fs.readFile);
    
11. 注意事项
  • 文件权限:确保 Node.js 进程有足够权限访问文件。
  • 跨平台兼容性:Windows 和 Unix 系统的路径分隔符不同,使用 path 模块处理。
  • 性能考量:频繁的文件操作可能成为性能瓶颈,考虑缓存策略。

总结

fs 模块是 Node.js 核心能力之一,提供了丰富的文件系统操作接口。根据场景选择合适的 API 风格(同步、回调或 Promise),并遵循最佳实践以确保代码健壮性和性能。对于复杂操作,推荐使用 Promise API 和 async/await 语法提高代码可读性。

const fs = require('fs').promises;

async function example() {
  try {
    const data = await fs.readFile('<file-path>', 'utf8');
    console.log(data);
    
    await fs.writeFile('<new-file-path>', '一些内容');
    console.log('文件已保存');
  } catch (err) {
    console.error(err);
  }
}

example();

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

chxii

小小打赏,大大鼓励!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值