2023-02-17 21:21:17
使用Node.js流处理大规模文件读写的核心是通过可读流(Readable Stream)和可写流(Writable Stream)实现分块数据传输,结合.pipe()方法自动管理背压(backpressure),避免内存溢出。以下链枝是具体实现方案和关键细节:
一、基础文件复制示例const fs = require('fs');const path = require('path');const sourcePath = path.join(__dirname, 'large_input.txt');const destinationPath = path.join(__dirname, 'large_output.txt');// 创建可读流(每次读取64KB)const readStream = fs.createReadStream(sourcePath, { highWaterMark: 64 * 1024 // 控制块大小});// 创建可写流const writeStream = fs.createWriteStream(destinationPath);// 错误处理readStream.on('error', (err) => { console.error('读取错误:', err); writeStream.destroy(); // 清理资源});writeStream.on('error', (err) => { console.error('写入错误:', err); readStream.destroy(); // 清理资源});// 完成事件writeStream.on('finish', () => { console.log('文件复制完成');});// 使用.pipe()自动传输数据并处理背压readStream.pipe(writeStream);关键点:
可读流(Readable Stream)
数据源(如fs.createReadStream),通过'data'事件或.pipe()输出数据块。
示例:从文件逐块读取数据。
可写流(Writable Stream)
数据目标(如fs.createWriteStream),接收数据块并写入。
示例:将数据写入文件或网络。
双工流(Duplex Stream)
同时具备可读和可写特性(如net.Socket),文件处理中较少直接使用。
转换流(Transform Stream)
特殊双工流,在传输过程中修改数据(如zlib压缩流)。
示例:棚搏敏实时压缩文件:const zlib = require('zlib');const readStream = fs.createReadStream('input.txt');const writeStream = fs.createWriteStream('input.txt.gz');const compressStream = zlib.createGzip();readStream.pipe(compressStream).pipe(writeStream);
错误处理
必须监听流的'error'事件,否则未捕获的错误会导致进程崩溃。
示例:双向错误处理readStream.on('error', (err) => { console.error('读取错误:', err); writeStream.end(); // 终止写入流});writeStream.on('error', (err) => { console.error('写入错误:', err); readStream.destroy(); // 终止读取流});
背压(Backpressure)
自动处理:.pipe()通过监听'drain'事件和write()返回值自动暂停/恢复读取。
手动处理场景:需在中间操作(如耗时计算)中控制流速:let isBackpressureActive = false;readStream.on('data', (chunk) => { if (isBackpressureActive) return; const canContinue = writeStream.write(chunk); if (!canContinue) { isBackpressureActive = true; readStream.pause(); console.log('背压触发:暂停读取'); }});writeStream.on('drain', () => { isBackpressureActive = false; readStream.resume(); console.log('背压解除:恢复读取');});
通过流式处理,Node.js可高效处理GB级甚至TB级文件,同时保持低内存占用和系统响应能力。