在node.js中如何实现fs文件系统目录操作与文件信息操作?
在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模块的目录与文件信息操作方法,涵盖目录创建删除、遍历递归、文件状态读取、权限修改、流式处理等核心功能,结合代码示例说明异步/同步模式差异,提供文件监控、符号链接等高级应用场景的实现方案,并总结错误处理与性能优化最佳实践。