Node.js实现大JSON文件内容追加及正确格式化方案咨询
大JSON数组文件追加合并方案
核心思路
因为文件体积大(超50K行),不能一次性加载到内存,必须用流式处理:
- 截断原JSON数组文件的结尾
] - 写入逗号作为元素分隔符
- 读取待追加的JSON数组文件,跳过开头的
[,将所有元素内容追加到原文件 - 最后写入
],恢复合法的JSON数组结构
具体实现(Node.js)
1. 依赖模块
仅需Node.js内置的fs和stream模块,无需额外安装第三方包。
2. 代码示例
const fs = require('fs'); const { Transform } = require('stream'); async function mergeJsonArrays(sourcePath, appendPath) { // 第一步:处理源文件,截断末尾的] const sourceStats = await fs.promises.stat(sourcePath); let endPosition = sourceStats.size; // 从文件末尾反向读取,找到真正的]位置(处理可能的换行/空格) const buffer = Buffer.alloc(1024); const fd = await fs.promises.open(sourcePath, 'r+'); let found = false; while (endPosition > 0 && !found) { const readSize = Math.min(1024, endPosition); await fd.read(buffer, 0, readSize, endPosition - readSize); for (let i = readSize - 1; i >= 0; i--) { if (buffer[i] === 93) { // ASCII码对应] endPosition = endPosition - readSize + i; found = true; break; } } if (!found) endPosition -= readSize; } if (!found) { await fd.close(); throw new Error('源文件不是合法的JSON数组'); } // 截断到]之前的位置 await fd.truncate(endPosition); // 写入逗号分隔符 await fd.write(',', endPosition); await fd.close(); // 第二步:追加待合并的JSON数组内容(跳过开头的[) const skipPrefix = new Transform({ transform(chunk, encoding, callback) { if (!this.prefixSkipped) { // 找到第一个[的位置,截取之后的内容 const str = chunk.toString(); const bracketIndex = str.indexOf('['); if (bracketIndex !== -1) { this.push(str.slice(bracketIndex + 1)); this.prefixSkipped = true; } else { // 整个chunk里没有[,直接丢弃 this.push(''); } } else { this.push(chunk); } callback(); } }); await new Promise((resolve, reject) => { const readStream = fs.createReadStream(appendPath); const writeStream = fs.createWriteStream(sourcePath, { flags: 'a' }); readStream .pipe(skipPrefix) .pipe(writeStream) .on('finish', resolve) .on('error', reject); }); // 第三步:写入结尾的],恢复合法JSON结构 await fs.promises.appendFile(sourcePath, ']'); } // 使用示例 mergeJsonArrays('./source.json', './to-append.json') .then(() => console.log('合并完成')) .catch(err => console.error('合并失败:', err));
关键注意事项
- 格式校验:确保两个输入文件都是合法的JSON数组,否则合并后会生成无效JSON。可以先用
JSON.parse验证小片段,或在流处理中增加格式检查逻辑。 - 内存优化:所有操作都是流式处理,不会一次性加载整个文件,避免内存溢出。
- 备份原文件:合并前务必备份源文件,防止操作失误导致数据丢失。
- 异常处理:代码中加入了基础的错误捕获,实际使用时可扩展处理文件权限、磁盘空间不足等场景。
常见问题修正
如果之前用fs.readFile直接读取整个文件导致内存问题,替换成上述流式处理即可解决;如果合并后JSON格式错误,大概率是没有正确处理数组的[和],或是源文件末尾有多余空格/换行,代码中反向查找]的逻辑已处理这类情况。
内容的提问来源于stack exchange,提问作者Harihara Ganesh
相关产品推荐
相关产品推荐

