web前端

node读写大文件

2022-05-18  本文已影响0人  姜治宇

如果读取小文件,我们可以使用fs读取,fs读取文件的时候,是将文件一次性读取到本地内存。而如果读取一个大文件,一次性读取会占用大量内存(Buffer对象),尤其是当我们读写g级的二进制大文件时,使用fs.readFileSync和fs.writeFileSync会报错:

ERROR [ExceptionsHandler] File size (2516230826) is greater than 2 GB

这个时候我们需要用流来解决了。

流是将数据分割成一段一段的读取,可以不会占用太大的内存。比如我们经常使用的gulp建立task任务,还有文件压缩、http中的请求和响应等都是流来实现的。
所有流都是 EventEmitter 的实例,所以不同的流也具有不同的事件,事件也就是告知外界自己自身的工作状态的方式。
流的事件有以下几个:
open - 打开文件
data - 当有数据可读时触发
error - 在读收和写入过程中发生错误时触发
close - 关闭文件
end - 没有更多的数据可读时触发
我们可以将流的读写封装到Promise:

const { rejects } = require('assert');
const fs = require('fs');
const path = require('path');

let srcPath = path.join('D:','big.zip');
let destPath = path.join('E:','zip','tt.zip');
console.log('执行开始...');

handleStream().then(res => {
    console.log(res);
    if (res && res.code === 200) {
        console.log('执行完毕');
    }

});

function handleStream() {
    return new Promise(resolve => {
        //大文件处理,执行过程会阻塞等待
        let rs = fs.createReadStream(srcPath, { encoding: 'binary' });
        let ws = fs.createWriteStream(destPath, { encoding: 'binary' });

        rs.on('data', (chunk) => {
            console.log('传输中');
            if (!ws.write(chunk)) { //如果还没写就先暂停
                console.log('读取暂停');
                rs.pause();
            }
        });
        ws.on('drain', () => {
            console.log('读取继续');
            rs.resume();

        });
        rs.on('err', (err) => {
            rejects({ code: -1, msg: '读取错误' });
        });

        rs.on('end', () => {
            console.log('end');
            ws.end();
            resolve({ code: 200, data: 'ok' });
        });
    });

}
上一篇下一篇

猜你喜欢

热点阅读