面试题答案
一键面试项目架构设计思路
- 模块拆分:将文件压缩解压功能拆分为不同的模块,如压缩模块、解压模块、错误处理模块、配置模块等,提高代码的可维护性和复用性。
- 错误处理:
- 文件相关错误:在打开文件、读取文件、写入文件等操作时,捕获错误并进行相应处理。例如权限不足错误(
EACCES
),文件不存在错误(ENOENT
)等。 - 压缩解压错误:在压缩和解压流的
error
事件中捕获错误,如解压时文件损坏可能导致的校验和错误等。
- 文件相关错误:在打开文件、读取文件、写入文件等操作时,捕获错误并进行相应处理。例如权限不足错误(
- 性能优化:
- Stream 合理使用:利用 Node.js 的
Stream
特性,实现数据的流式处理,避免一次性加载整个文件到内存,从而提升性能。 - 多线程与多核利用:虽然 Node.js 是单线程的,但可以通过
child_process
模块创建子进程,充分利用多核 CPU 的优势。每个子进程可以独立处理一部分文件的压缩或解压任务。
- Stream 合理使用:利用 Node.js 的
关键代码片段
压缩模块
const { createGzip } = require('zlib');
const { createReadStream, createWriteStream } = require('fs');
function compressFile(sourceFilePath, targetFilePath) {
const readStream = createReadStream(sourceFilePath);
const writeStream = createWriteStream(targetFilePath);
const gzip = createGzip();
readStream.on('error', (err) => {
console.error(`读取文件错误: ${err.message}`);
// 处理读取文件错误,如关闭写入流等操作
writeStream.end();
});
writeStream.on('error', (err) => {
console.error(`写入文件错误: ${err.message}`);
// 处理写入文件错误,如关闭读取流等操作
readStream.destroy();
});
gzip.on('error', (err) => {
console.error(`压缩错误: ${err.message}`);
// 处理压缩错误,如关闭读取流和写入流
readStream.destroy();
writeStream.end();
});
readStream.pipe(gzip).pipe(writeStream);
}
解压模块
const { createGunzip } = require('zlib');
const { createReadStream, createWriteStream } = require('fs');
function decompressFile(sourceFilePath, targetFilePath) {
const readStream = createReadStream(sourceFilePath);
const writeStream = createWriteStream(targetFilePath);
const gunzip = createGunzip();
readStream.on('error', (err) => {
console.error(`读取文件错误: ${err.message}`);
// 处理读取文件错误,如关闭写入流等操作
writeStream.end();
});
writeStream.on('error', (err) => {
console.error(`写入文件错误: ${err.message}`);
// 处理写入文件错误,如关闭读取流等操作
readStream.destroy();
});
gunzip.on('error', (err) => {
console.error(`解压错误: ${err.message}`);
// 处理解压错误,如关闭读取流和写入流
readStream.destroy();
writeStream.end();
});
readStream.pipe(gunzip).pipe(writeStream);
}
多进程处理示例
const { fork } = require('child_process');
function compressFilesInParallel(sourceFilePaths, targetFilePaths) {
const numFiles = sourceFilePaths.length;
const childProcesses = [];
for (let i = 0; i < numFiles; i++) {
const child = fork('./compressWorker.js');
child.send({ sourceFilePath: sourceFilePaths[i], targetFilePath: targetFilePaths[i] });
childProcesses.push(child);
child.on('error', (err) => {
console.error(`子进程错误: ${err.message}`);
});
child.on('exit', (code) => {
if (code === 0) {
console.log(`子进程 ${i} 压缩完成`);
} else {
console.error(`子进程 ${i} 压缩失败,退出码: ${code}`);
}
});
}
}
// compressWorker.js 内容示例
process.on('message', (msg) => {
const { sourceFilePath, targetFilePath } = msg;
// 调用上述压缩函数进行文件压缩
compressFile(sourceFilePath, targetFilePath);
process.exit(0);
});
通过以上设计思路和代码片段,可以构建一个健壮且高效的文件压缩解压模块。