NodeJS处理1.5GB大文本文件末尾:修复JSON格式问题
Node.js处理大文件生成合法JSON的方案
针对1.5GB的大文件,绝对不能一次性加载到内存处理,否则会直接导致内存溢出。下面提供两种高效的Node.js实现方案:
方案一:直接定位修改文件末尾(最优)
利用文件系统的随机读写能力,只操作文件末尾的少量内容,性能最高:
const fs = require('fs').promises; const path = require('path'); async function fixLargeJsonFile(filePath) { // 打开文件,获取文件描述符 const fd = await fs.open(filePath, 'r+'); try { // 获取文件总大小 const { size } = await fd.stat(); if (size === 0) { await fd.write('[]'); return; } // 从文件末尾往前逐字节读取,寻找最后一个逗号的位置 let pos = size - 1; let foundComma = false; // 最多往前检查100字节(足够覆盖末尾的换行、空格等) while (pos > 0 && pos >= size - 100) { const buffer = Buffer.alloc(1); await fd.read(buffer, 0, 1, pos); const char = buffer.toString(); // 跳过换行、空格等空白字符 if (char === '\n' || char === '\r' || char === ' ') { pos--; continue; } if (char === ',') { // 找到最后一个逗号,覆盖为']' await fd.write(Buffer.from(']'), 0, 1, pos); foundComma = true; break; } else { // 如果末尾没有逗号,直接追加']'(防止异常情况) await fd.write(Buffer.from(']'), 0, 1, size); break; } } // 如果没找到逗号(比如文件只有开头的'['),补全为'[]' if (!foundComma && pos === 0) { await fd.write(Buffer.from(']'), 0, 1, 1); } } finally { await fd.close(); } } // 使用示例 fixLargeJsonFile('./your-large-file.txt') .then(() => console.log('文件修复完成')) .catch(err => console.error('修复失败:', err));
方案说明:
- 仅操作文件末尾最多100字节,完全避免加载大文件到内存
- 自动跳过末尾的换行、空格等空白字符,适配不同的文件结尾格式
- 包含异常情况处理(空文件、无逗号的情况)
方案二:流式反向读取(兼容复杂场景)
如果文件末尾的空白字符较多,或者需要更灵活的匹配,可以用流式反向读取:
const fs = require('fs'); const { createReadStream } = require('fs'); const { promisify } = require('util'); const truncate = promisify(fs.truncate); const appendFile = promisify(fs.appendFile); function fixLargeJsonFileStream(filePath) { return new Promise((resolve, reject) => { const stats = fs.statSync(filePath); let currentPos = stats.size; let foundComma = false; // 创建从末尾反向读取的流 const stream = createReadStream(filePath, { start: Math.max(0, currentPos - 1024), end: currentPos - 1, highWaterMark: 1 }); stream.on('data', (chunk) => { stream.pause(); currentPos--; const char = chunk.toString(); if (char === '\n' || char === '\r' || char === ' ') { stream.resume(); return; } if (char === ',') { // 截断到逗号位置,然后追加']' truncate(filePath, currentPos) .then(() => appendFile(filePath, ']')) .then(resolve) .catch(reject); foundComma = true; stream.destroy(); } else { // 无逗号,直接追加']' appendFile(filePath, ']') .then(resolve) .catch(reject); stream.destroy(); } }); stream.on('end', () => { if (!foundComma) { // 整个文件读完没找到逗号,说明只有'[',补全为'[]' appendFile(filePath, ']').then(resolve).catch(reject); } }); stream.on('error', reject); }); } // 使用示例 fixLargeJsonFileStream('./your-large-file.txt') .then(() => console.log('文件修复完成')) .catch(err => console.error('修复失败:', err));
方案说明:
- 以1字节为单位反向读取,确保精准定位最后一个逗号
- 同样避免加载整个文件,仅读取末尾的1KB内容(可调整)
- 适合末尾有大量空白字符的场景
内容的提问来源于stack exchange,提问作者blueway
相关产品推荐
相关产品推荐

