位置: 文档库 > JavaScript > 在node.js中如何实现fs文件系统目录操作与文件信息操作?

在node.js中如何实现fs文件系统目录操作与文件信息操作?

海龟先生 上传于 2023-01-13 12:49

在Node.js中如何实现fs文件系统目录操作与文件信息操作?

Node.js作为基于Chrome V8引擎的JavaScript运行时环境,其核心模块之一fs(File System)提供了对文件系统的完整操作能力。通过fs模块,开发者可以以同步或异步方式实现目录创建、遍历、删除,以及文件信息读取、修改等操作。本文将系统梳理fs模块的核心功能,结合代码示例与实际应用场景,深入解析目录与文件信息操作的实现方法。

一、fs模块基础与初始化

fs模块是Node.js内置模块,无需安装即可直接引入。其提供同步(Sync)和异步(Async)两种操作模式,异步方法采用回调函数或Promise(Node.js 10+支持)处理结果,同步方法则通过返回值直接获取结果。

const fs = require('fs');
// 或使用Promise版本(Node.js 10+)
const fsPromises = require('fs').promises;

异步模式推荐用于I/O密集型操作,避免阻塞事件循环;同步模式适用于脚本初始化或简单工具开发。以下示例对比两种模式的文件读取:

// 异步读取
fs.readFile('test.txt', 'utf8', (err, data) => {
  if (err) throw err;
  console.log(data);
});

// 同步读取
try {
  const data = fs.readFileSync('test.txt', 'utf8');
  console.log(data);
} catch (err) {
  console.error(err);
}

二、目录操作核心方法

1. 目录创建与删除

(1)创建目录:使用fs.mkdir()fs.mkdirSync(),支持递归创建(Node.js 10.12+)。

// 异步创建单层目录
fs.mkdir('./newDir', (err) => {
  if (err) throw err;
  console.log('目录创建成功');
});

// 递归创建多级目录
fs.mkdir('./a/b/c', { recursive: true }, (err) => {
  if (err) throw err;
});

// 同步版本
fs.mkdirSync('./syncDir', { recursive: true });

(2)删除目录:fs.rmdir()(Node.js 14+已废弃)和fs.rm()(推荐)。

// 删除空目录(旧方法,不推荐)
fs.rmdir('./emptyDir', (err) => {
  if (err) throw err;
});

// 递归删除目录及内容(Node.js 14.14+)
fs.rm('./fullDir', { recursive: true, force: true }, (err) => {
  if (err) throw err;
});

// 同步删除
fs.rmSync('./syncDir', { recursive: true });

2. 目录遍历与内容读取

(1)读取目录内容:fs.readdir()返回文件/子目录名称数组。

fs.readdir('./', (err, files) => {
  if (err) throw err;
  console.log(files); // 输出: ['file1.txt', 'subdir']
});

(2)递归遍历目录树:结合fs.stat()判断类型,实现深度优先遍历。

function traverseDir(path) {
  fs.readdir(path, { withFileTypes: true }, (err, dirents) => {
    if (err) throw err;
    dirents.forEach(dirent => {
      const fullPath = `${path}/${dirent.name}`;
      if (dirent.isDirectory()) {
        traverseDir(fullPath); // 递归子目录
      } else {
        console.log(`文件: ${fullPath}`);
      }
    });
  });
}
traverseDir('./');

(3)使用withFileTypes: true选项可获取fs.Dirent对象,避免重复调用fs.stat()

三、文件信息操作详解

1. 文件状态获取

(1)基础信息:fs.stat()返回包含大小、修改时间等的fs.Stats对象。

fs.stat('test.txt', (err, stats) => {
  if (err) throw err;
  console.log(`大小: ${stats.size}字节`);
  console.log(`修改时间: ${new Date(stats.mtime)}`);
  console.log(`是否为文件: ${stats.isFile()}`);
  console.log(`是否为目录: ${stats.isDirectory()}`);
});

(2)符号链接处理:使用fs.lstat()获取链接本身信息,fs.stat()会跟随链接。

2. 文件属性修改

(1)修改权限:fs.chmod()设置文件模式(需八进制数)。

fs.chmod('test.txt', 0o755, (err) => {
  if (err) throw err;
  console.log('权限修改成功');
});

(2)修改所有者:fs.chown()(需管理员权限)。

fs.chown('test.txt', 1000, 1000, (err) => {
  if (err) throw err;
});

(3)修改时间戳:fs.utimes()更新访问和修改时间。

const now = new Date();
fs.utimes('test.txt', now, now, (err) => {
  if (err) throw err;
});

3. 文件内容操作

(1)写入文件:fs.writeFile()覆盖写入,fs.appendFile()追加内容。

fs.writeFile('new.txt', 'Hello World', 'utf8', (err) => {
  if (err) throw err;
});

fs.appendFile('new.txt', '\nAppended line', (err) => {
  if (err) throw err;
});

(2)流式操作:处理大文件时使用fs.createReadStream()fs.createWriteStream()

const readStream = fs.createReadStream('large.txt');
const writeStream = fs.createWriteStream('copy.txt');
readStream.pipe(writeStream);

四、高级应用场景

1. 文件监控:fs.watch()fs.watchFile()

(1)简单监控:fs.watch()返回fs.FSWatcher对象。

const watcher = fs.watch('test.txt', (eventType, filename) => {
  console.log(`文件 ${filename} 发生 ${eventType} 事件`);
});
// 停止监控
// watcher.close();

(2)轮询监控:fs.watchFile()使用统计信息检测变化。

fs.watchFile('test.txt', (curr, prev) => {
  if (curr.mtime > prev.mtime) {
    console.log('文件被修改');
  }
});

2. 符号链接操作

(1)创建符号链接:fs.symlink()

fs.symlink('./target.txt', './link.txt', (err) => {
  if (err) throw err;
});

(2)读取链接目标:fs.readlink()

fs.readlink('./link.txt', (err, linkString) => {
  if (err) throw err;
  console.log(linkString); // 输出: ./target.txt
});

3. 跨平台路径处理

使用path模块处理路径分隔符差异:

const path = require('path');
const fullPath = path.join(__dirname, 'subdir', 'file.txt');

五、错误处理与最佳实践

1. 异步操作必须处理错误回调,同步操作使用try-catch。

2. 递归操作时注意堆栈溢出,深度过大时改用异步递归。

3. 文件路径建议使用绝对路径,避免相对路径导致的意外行为。

4. 大文件操作优先使用流(Stream)而非缓冲(Buffer)。

5. 权限操作需确保进程有足够权限(如Linux下的sudo)。

六、完整示例:文件管理器核心功能

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

async function listDirectory(dir) {
  try {
    const dirents = await fs.readdir(dir, { withFileTypes: true });
    for (const dirent of dirents) {
      const fullPath = path.join(dir, dirent.name);
      const stats = await fs.stat(fullPath);
      console.log(`${dirent.isDirectory() ? 'D' : 'F'} ${stats.size}B ${fullPath}`);
    }
  } catch (err) {
    console.error(`读取目录失败: ${err}`);
  }
}

async function createFileIfNotExists(filePath, content = '') {
  try {
    await fs.access(filePath);
    console.log('文件已存在');
  } catch {
    await fs.writeFile(filePath, content);
    console.log('文件创建成功');
  }
}

// 使用示例
listDirectory('./');
createFileIfNotExists('./newFile.txt', '初始内容');

关键词:Node.js、fs模块、目录操作、文件信息、异步I/O、文件监控、符号链接、流处理

简介:本文详细解析Node.js中fs模块的目录与文件信息操作方法,涵盖目录创建删除、遍历递归、文件状态读取、权限修改、流式处理等核心功能,结合代码示例说明异步/同步模式差异,提供文件监控、符号链接等高级应用场景的实现方案,并总结错误处理与性能优化最佳实践。