目录操作
文件系统基础
Node.js 提供了 fs
模块来处理文件系统操作。这个模块包含同步和异步两种方法,其中异步方法通常更受欢迎,因为它们不会阻塞事件循环。要使用 fs
模块,首先需要引入它:
const fs = require('fs');
const fsPromises = require('fs').promises; // Promise版本
创建目录
创建目录是目录操作中最基本的任务之一。Node.js 提供了 mkdir()
和 mkdirSync()
方法来实现这一功能。
// 异步创建目录
fs.mkdir('new-directory', (err) => {
if (err) throw err;
console.log('目录创建成功');
});
// 同步创建目录
try {
fs.mkdirSync('new-directory-sync');
console.log('同步方式目录创建成功');
} catch (err) {
console.error(err);
}
// 使用Promise创建目录
async function createDir() {
try {
await fsPromises.mkdir('new-directory-promise');
console.log('Promise方式目录创建成功');
} catch (err) {
console.error(err);
}
}
createDir();
递归创建目录
有时候需要创建多层嵌套的目录结构,可以使用 recursive
选项:
// 递归创建目录
fs.mkdir('parent/child/grandchild', { recursive: true }, (err) => {
if (err) throw err;
console.log('递归目录创建成功');
});
读取目录内容
读取目录内容是常见的操作,可以使用 readdir()
方法:
// 异步读取目录
fs.readdir('./', (err, files) => {
if (err) throw err;
console.log('目录内容:', files);
});
// 同步读取目录
try {
const files = fs.readdirSync('./');
console.log('同步方式读取目录内容:', files);
} catch (err) {
console.error(err);
}
// 使用Promise读取目录
async function readDir() {
try {
const files = await fsPromises.readdir('./');
console.log('Promise方式读取目录内容:', files);
} catch (err) {
console.error(err);
}
}
readDir();
获取目录详细信息
有时需要获取目录的详细信息,如创建时间、修改时间等:
// 获取目录状态
fs.stat('some-directory', (err, stats) => {
if (err) throw err;
console.log('是否是目录:', stats.isDirectory());
console.log('创建时间:', stats.birthtime);
console.log('修改时间:', stats.mtime);
});
重命名目录
重命名目录可以使用 rename()
方法:
// 重命名目录
fs.rename('old-name', 'new-name', (err) => {
if (err) throw err;
console.log('目录重命名成功');
});
删除目录
删除目录有几种不同的方法,取决于目录是否为空:
// 删除空目录
fs.rmdir('empty-directory', (err) => {
if (err) throw err;
console.log('空目录删除成功');
});
// 递归删除非空目录
fs.rm('non-empty-directory', { recursive: true }, (err) => {
if (err) throw err;
console.log('非空目录删除成功');
});
目录操作实用技巧
检查目录是否存在
function directoryExists(path) {
try {
return fs.statSync(path).isDirectory();
} catch (err) {
return false;
}
}
遍历目录树
function walkDir(dir, callback) {
fs.readdirSync(dir).forEach(f => {
let dirPath = path.join(dir, f);
let isDirectory = fs.statSync(dirPath).isDirectory();
isDirectory ? walkDir(dirPath, callback) : callback(path.join(dir, f));
});
}
walkDir('./', file => console.log(file));
创建临时目录
const os = require('os');
const path = require('path');
const tempDir = path.join(os.tmpdir(), 'my-temp-dir');
fs.mkdirSync(tempDir);
目录操作中的错误处理
正确处理目录操作中的错误非常重要:
fs.readdir('/nonexistent', (err, files) => {
if (err) {
if (err.code === 'ENOENT') {
console.error('目录不存在');
} else {
console.error('发生未知错误:', err);
}
return;
}
console.log(files);
});
性能考虑
在处理大量目录操作时,性能成为一个重要因素:
- 同步方法会阻塞事件循环,在性能关键的应用中应避免使用
- 批量操作时,考虑使用流或工作队列
- 对于频繁访问的目录,可以缓存目录内容
// 使用工作队列处理大量目录操作
const { Worker, isMainThread, workerData } = require('worker_threads');
if (isMainThread) {
const worker = new Worker(__filename, {
workerData: { dir: './large-directory' }
});
} else {
processDir(workerData.dir);
}
function processDir(dir) {
// 处理目录的繁重任务
}
跨平台注意事项
不同操作系统对目录的处理有差异:
- Windows 使用反斜杠()作为路径分隔符,而Unix使用斜杠(/)
- 路径大小写敏感性在不同系统上表现不同
- 使用
path
模块处理路径可以避免这些问题
const path = require('path');
// 跨平台路径连接
const fullPath = path.join('dir', 'subdir', 'file.txt');
高级目录监控
Node.js 提供了 fs.watch()
方法来监控目录变化:
// 监控目录变化
const watcher = fs.watch('./watched-dir', (eventType, filename) => {
console.log(`事件类型: ${eventType}`);
if (filename) {
console.log(`文件名: ${filename}`);
}
});
// 停止监控
setTimeout(() => {
watcher.close();
}, 10000);
目录操作与流结合
将目录操作与流结合可以高效处理大量文件:
const { Readable } = require('stream');
class DirectoryStream extends Readable {
constructor(dir) {
super({ objectMode: true });
this.dir = dir;
this.files = fs.readdirSync(dir);
this.index = 0;
}
_read() {
if (this.index < this.files.length) {
this.push(path.join(this.dir, this.files[this.index++]));
} else {
this.push(null);
}
}
}
const dirStream = new DirectoryStream('./large-dir');
dirStream.on('data', file => console.log(file));
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn