Node.js读取2GB以上JSON文件报ERR_FS_FILE_TOO_LARGE错误如何解决
报错根因
你遇到的ERR_FS_FILE_TOO_LARGE错误是Node.js内置fs.readFile API的固有限制:该接口会一次性将整个文件加载到内存中,默认最大支持的文件大小为2GB,你的文件大小为3.4GB,超出限制所以触发报错。就算绕过该限制,一次性加载数GB的文件到内存也极容易触发内存溢出,本身也不是处理大文件的合理方案。
修复方案
改用流式逐行读取逻辑,利用Node.js内置的fs.createReadStream和readline模块,边读取文件行、边处理数据、边批量导入Elasticsearch,全程内存占用可以稳定在百MB级别,完全适配大文件处理场景。
你的原文件是每行一个独立JSON结构,正好匹配逐行处理的逻辑,修改后的完整可运行代码如下:
const fs = require('fs'); const readline = require('readline'); // 确保你已经正确初始化了ES客户端client,这里沿用你原有逻辑 // 批量请求缓存队列 let bulk_request = []; let busy = false; // 处理批量插入ES的公共逻辑 const flushBulk = async () => { if (busy || bulk_request.length === 0) return; busy = true; try { await client.bulk({ // ES 7.x及以上版本已经废弃自定义_type,统一用_doc,如果是老版本可以保留你原来的tweets body: bulk_request }); console.log(`已批量插入${bulk_request.length / 2}条数据`); bulk_request = []; } catch (err) { console.error('批量插入失败:', err); } finally { busy = false; } }; // 创建逐行读取实例 const rl = readline.createInterface({ input: fs.createReadStream('GOV.json', { encoding: 'utf-8' }), crlfDelay: Infinity }); // 逐行处理逻辑 rl.on('line', (line) => { if (!line.trim()) return; let obj; try { obj = JSON.parse(line); } catch (e) { console.log('跳过格式非法的行'); return; } // 整理数据,沿用你原有逻辑 const tweet = { id: obj.id, username: obj.username, tweet: obj.tweet, date: new Date(obj.date), url: obj.url }; // 组装批量请求 bulk_request.push({ index: { _index: 'tweets_index', _id: tweet.id } }); bulk_request.push(tweet); // 攒够1000条就触发一次批量插入 if (bulk_request.length >= 2000) { // 每条数据对应两个请求体元素,所以2000就是1000条数据 flushBulk(); // 如果写入速度跟不上读取速度,暂停读取防止内存堆积 if (busy) { rl.pause(); } } }); // 读取完成后处理剩余的不足1000条的数据 rl.on('close', async () => { await flushBulk(); console.log('所有记录插入完成'); }); // 插入完成后恢复读取 rl.on('resume', () => { console.log('恢复文件读取'); });
额外注意事项
- 如果使用的是Elasticsearch 7.x及以上版本,需要删除请求中的
_type: "tweets"参数,该版本开始已经废弃自定义类型,统一使用_doc,不需要手动指定 - 可以根据你的服务器配置调整单次批量插入的条数,服务器性能好可以调整到2000-3000条/次,插入效率更高
- 如果出现ES写入超时,可以适当调高
client.bulk的超时参数
内容的提问来源于stack exchange,提问作者Drsaud
相关产品推荐
相关产品推荐

