node实现可读流---源码解析

先介绍一下fs.createReadStream

fs.createReadStream(path,options)

//第一个参数
path //文件绝对路径

//第二个参数
options //是一个对象
{
    flags: "r", //r代表读取
    // encoding:null,
    mode: 0o666, //可读可写
    autoClose: true, //fs.close 读取完毕后关闭
    start: 0, //从第几位读取 包前又包后
    end: 9, //读取到第几位 
    highWaterMark: 3  //每次读取的个数
}

实现一个可读流

const Emitter = require("events");
var fs = require("fs");
class ReadStream extends Emitter {
    constructor(p, ops = {}) {
        super();
        this.path = p;
        this.flags = ops.flags || 'r';
        this.mode = ops.mode || 0o666;
        this.autoClose = ops.autoClose || true;
        this.start = ops.start || 0;
        this.end = ops.end;
        this.highWaterMark = ops.highWaterMark || 64 * 1024;
        //纪录偏移量
        this.pos = this.start;
        //看是否监听了data事件 监听data为流动模式 否则为非流动模式
        this.flowing = false;
        this.on("newListener", (type) => {
            if (type === 'data') {
                this.flowing = true;
                this.read()
            }
        })
        this.openFile(); //打开文件 fs.open
    }
    openFile() {
        fs.open(this.path, this.flags, this.mode, (err, fd) => {
            if (err) {
                return this.emit("error", err)
            }
            this.fd = fd; //保存在实例上 用于后面的读取操作
            this.emit('open', fd);
        })
    }
    read() {
        if (typeof this.fd !== 'number') {
            return this.once('open', () => { this.read() })
        }
        let buffer = Buffer.alloc(this.highWaterMark);
        // console.log(this.fd + '------')
        let howMuchToRead = this.end ? Math.min(this.end - this.pos + 1, this.highWaterMark) : this.highWaterMark;
        fs.read(this.fd, buffer, 0, howMuchToRead, this.pos, (err, bytesRead) => {
                if (bytesRead) {
                    this.pos += bytesRead;
                    this.emit('data', buffer.slice(0, bytesRead));
                    if (this.flowing) {
                        this.read();
                    }
                } else {//读取完毕
                    this.emit('end');
                    if (this.autoClose) {
                        this.emit('close');
                    }
                }
            
              if(err){  
                 this.emit('error',err);
               }      
        })
    }
    pause(){
        this.flowing = false;
    }
    resume(){
        this.flowing = true;
        this.read();
    }
}
module.exports = ReadStream

业务层代码

var ReadStream = require("./readStream");
var path = require("path");


var rs = new ReadStream(path.resolve(__dirname, 'name.txt'), {
    flags: "r", //r代表读取
    // encoding:null,//默认buffer
    mode: 0o666, //可读可写
    autoClose: true, //fs.close 读取完毕后关闭
    start: 0, //从第几位读取 包前又包后
    end: 9, //读取到第几位 
    highWaterMark: 3  //每次读取的个数
})

let bufferArr = [];
rs.on("open", (fd) => {
    console.log(fd);
})

rs.on("data", (data) => {
    bufferArr.push(data)
    rs.pause()
    setTimeout(() => {
        rs.resume();
        console.log("触发");
    }, 1000)
});

rs.on('end', () => {
    console.log(Buffer.concat(bufferArr).toString());
})

rs.on('close', () => {
    console.log('close');
})

rs.on("error", (err) => {
    console.log(err)
})

响应结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值