如何在NodeJS中读取目录下程序文件内容并生成内容数组
优化目录文件内容读取方案(解决大文件内存问题与异步逻辑缺陷)
原代码存在的核心问题
- 错误处理逻辑失效:
if(err)分支错误地将data(此时为undefined)推入数组,未正确捕获或跳过错误文件 - 异步索引混乱:
for循环的i在异步回调执行时已被修改,导致console.log(directoryFileContents[i])无法输出对应文件的内容 - 大文件内存压力:
fs.readFile会一次性将整个文件加载到内存,处理package-lock.json这类大体积文件时,极易引发内存占用过高问题
推荐优化方案
方案1:使用fs.promises + async/await(异步非阻塞,可控制并发)
采用Promise化的文件API,配合async/await简化异步逻辑,同时通过并发数限制避免同时读取多个大文件导致内存暴涨:
const fs = require('fs').promises; const path = require('path'); async function readAllFiles(directory, directoryFiles) { const directoryFileContents = []; // 限制并发读取数,根据内存情况调整 const concurrencyLimit = 3; let activeTasks = 0; const taskQueue = []; // 生成所有读取任务 for (const filename of directoryFiles) { const filePath = path.join(directory, filename); taskQueue.push(async () => { try { const data = await fs.readFile(filePath, 'utf-8'); directoryFileContents.push({ filename, content: data }); } catch (err) { console.error(`读取失败:${filePath}`, err.message); // 可选择记录错误或跳过错误文件 directoryFileContents.push({ filename, error: err.message }); } }); } // 控制并发执行任务 for (const task of taskQueue) { if (activeTasks >= concurrencyLimit) { await new Promise(resolve => setImmediate(resolve)); } activeTasks++; task().finally(() => activeTasks--); } // 等待所有任务完成 while (activeTasks > 0) { await new Promise(resolve => setImmediate(resolve)); } return directoryFileContents; } // 使用示例 // readAllFiles('./your-project-dir', ['index.js', 'package-lock.json']) // .then(contents => console.log('所有文件内容:', contents));
方案2:流式读取(针对超大文件)
如果不需要将完整文件内容存入数组,或可分块处理,用流式读取能大幅降低内存占用:
const fs = require('fs'); const path = require('path'); // 流式读取单个文件并拼接内容 function readFileStream(filePath) { return new Promise((resolve, reject) => { let content = ''; const stream = fs.createReadStream(filePath, 'utf-8'); stream.on('data', chunk => { content += chunk; // 可在此处添加分块处理逻辑,无需等待文件读完 }); stream.on('end', () => resolve(content)); stream.on('error', err => reject(err)); }); } // 结合async/await批量读取,用法同方案1
方案3:回调风格的基础修正(兼容旧代码)
如果必须保留回调写法,需修复索引问题和错误处理:
const fs = require('fs'); const path = require('path'); const directoryFileContents = []; let completedReads = 0; const totalFiles = directoryFiles.length; for (let i = 0; i < totalFiles; i++) { // 用闭包保存当前文件索引 (function(fileIndex) { const filePath = path.join(directory, directoryFiles[fileIndex]); fs.readFile(filePath, 'utf-8', (err, data) => { completedReads++; if (err) { console.error(`读取失败:${filePath}`, err.message); directoryFileContents[fileIndex] = { error: err.message }; } else { directoryFileContents[fileIndex] = data; } // 所有文件读取完成后执行后续逻辑 if (completedReads === totalFiles) { console.log('全部读取完成:', directoryFileContents); } }); })(i); }
内容的提问来源于stack exchange,提问作者BeratK2
相关产品推荐
相关产品推荐

