面试题答案
一键面试1. 跨平台兼容性
在Node.js中,fs
模块已经具备一定的跨平台能力。但为了确保更稳健的跨平台操作,可使用path
模块来处理文件路径。
const path = require('path');
const fs = require('fs');
// 使用path.join来拼接路径,确保跨平台兼容性
const targetDir = path.join(__dirname, 'target');
2. 遍历文件
为减少I/O阻塞,可使用fs.promises
的异步方法结合async/await
,同时采用递归方式遍历目录。
async function traverseDirectory(dir) {
let files = [];
try {
const items = await fs.promises.readdir(dir, { withFileTypes: true });
for (const item of items) {
const itemPath = path.join(dir, item.name);
if (item.isDirectory()) {
files = files.concat(await traverseDirectory(itemPath));
} else {
files.push(itemPath);
}
}
} catch (err) {
console.error('遍历目录出错:', err);
}
return files;
}
3. 筛选文件
根据具体筛选条件(如文件名、文件类型等)对遍历得到的文件列表进行筛选。
function filterFiles(files, filterCondition) {
return files.filter(file => {
// 例如,筛选出以.txt结尾的文件
if (filterCondition === 'txt') {
return path.extname(file) === '.txt';
}
return false;
});
}
4. 复制文件
同样使用fs.promises
的异步方法进行文件复制,可利用管道流(pipeline
)提高性能。
const { pipeline } = require('stream');
const { promisify } = require('util');
async function copyFile(source, target) {
try {
await promisify(pipeline)(
fs.createReadStream(source),
fs.createWriteStream(target)
);
} catch (err) {
console.error('复制文件出错:', err);
}
}
5. 重命名文件
使用fs.promises.rename
方法实现文件重命名。
async function renameFile(oldPath, newPath) {
try {
await fs.promises.rename(oldPath, newPath);
} catch (err) {
console.error('重命名文件出错:', err);
}
}
6. 性能优化 - 缓存
对于一些频繁访问的目录结构或文件信息,可以考虑使用内存缓存。例如,使用Map
对象来缓存已经遍历过的目录及其文件列表。
const cache = new Map();
async function traverseDirectoryCached(dir) {
if (cache.has(dir)) {
return cache.get(dir);
}
let files = [];
try {
const items = await fs.promises.readdir(dir, { withFileTypes: true });
for (const item of items) {
const itemPath = path.join(dir, item.name);
if (item.isDirectory()) {
files = files.concat(await traverseDirectoryCached(itemPath));
} else {
files.push(itemPath);
}
}
cache.set(dir, files);
} catch (err) {
console.error('遍历目录出错:', err);
}
return files;
}
7. 错误处理机制
在上述所有的异步操作中,都通过try...catch
块捕获错误,并进行相应的错误提示输出。在实际应用中,还可以根据错误类型进行更细致的处理,比如记录错误日志、向用户提供友好的错误反馈等。
// 示例:整体调用并处理错误
async function main() {
const sourceDir = path.join(__dirname,'source');
const targetDir = path.join(__dirname, 'target');
try {
const allFiles = await traverseDirectoryCached(sourceDir);
const filteredFiles = filterFiles(allFiles, 'txt');
for (const file of filteredFiles) {
const newFilePath = path.join(targetDir, path.basename(file));
await copyFile(file, newFilePath);
const newNamePath = path.join(targetDir, 'new_' + path.basename(file));
await renameFile(newFilePath, newNamePath);
}
} catch (err) {
console.error('整体操作出错:', err);
}
}
main();