Node ReadStream实现

node ReadStream 实现

fs.createReadStream 继承自 stream模块


const fs = require('fs');
const EventEmitter = require('events');

class ReadStream extends EventEmitter {
  constructor(path, options = {}) {
    super();
    this.path = path;
    this.encoding = options.encoding || 'utf8';
    this.flags = options.flags || 'r';
    this.mode = options.mode || 0o666;
    this.start = options.start || 0;
    this.pos = this.start;
    this.end = options.end;
    this.highWaterMark = options.highWaterMark || 16 * 1024;
    this.autoClose = options.autoClose || true;
    this.buffers = [];
    this.fd = undefined;
    this.flowing = false;
    this.length = 0;
    this.open();
    this.on('newListener', (type, event) => { // 监听newListenergkwr,一旦绑定新事件就会触发
      if (type === 'data') { // 如果监听了data事件,则进行数据读取,并将流动模式改为true
        this.read();
        this.flowing = true;
      }
    })
  }
  open() {
    fs.open(this.path, this.flags, this.mode, (err, fd) => {
      if (err) {
        if (this.autoClose) {
          this._destory();
        }
        this.emit('error', err);
      } else {
        this.fd = fd;
        this.emit('open', fd);
      }
    })
  }
  pause() {
    // 暂停读取
    this.flowing = false;
  }
  resume() {
    // 恢复读取
    this.flowing = true;
    this.read();
  }
  // 进行管道传输
  pipe(ws) {
    if (typeof this.fd !== 'number') {
      this.open();
    }
    this.on('data', data => {
      let flag = ws.write(data);
      if (!flag) {
        this.pause();
        // console.log(this.pause)
      }
    })
    // console.log('read: ' + this.fd)
    // console.log('wrte: ' + ws.fd)
    ws.on('drain', () => {
      // console.log(this)
      // this.resume();
      // console.log(this.resume)
    })
  }
  read() {
    if (typeof this.fd !== 'number') {
      // 判断文件是否已经打开,如果没有则绑定open事件,当文件打开后则再次进行read
      return this.once('open', () => this.read());
    }
    this._read();
  }
  _read() {
    // 计算要读取的长度,如果此时剩下的读取长度小于highWaterMark就用end结束长度减去当前的pos偏移量
    let howMuchRead = this.end ? Math.min(this.end - this.pos, this.highWaterMark) : this.highWaterMark;
    // console.log(this.end, this.end - this.pos + 1)
    let buffer = Buffer.alloc(howMuchRead); // 分配指定大小buffer数据传输区
    fs.read(this.fd, buffer, 0, howMuchRead, this.pos, (err, readBytes) => {
      if (err) {
        this.emit('error', err);
        this._destory();
      } else {
        if (readBytes) {
          this.pos += readBytes;
          this.emit('data', this.encoding === 'utf-8' ? buffer.slice(0, readBytes).toString() : buffer.slice(0, readBytes));
          if (this.flowing) {  // 如果是flowing流动模式,则继续读取
            this._read();
          }
        } else {
          // 数据读取完毕,触发end事件,并关闭fs文件读取通道
          this.emit('end');
          this._destory();
        }
      }
    })
  }
  // 销毁或关闭fs文件读取通道
  _destory() {
    fs.close(this.fd, (err) => {
      if (err) throw err;
      this.emit('close');
    })
  }
}

module.exports = ReadStream;

// 正面是测试代码
// const rs = new ReadStream('stream/2.writable.txt', {
//   highWaterMark: 3,
//   encoding: 'utf-8',
//   end: 13
// });
// rs.on('open', () => {
//   console.log('file open~');
// })
// rs.on('data', data => {
//   console.log(data);
//   rs.pause();
// })
// rs.on('end', () => {
//   console.log('read end');
// });
// rs.on('close', () => {
//   console.log('file close');
// })

// setInterval(() => {
//   rs.resume();
// },500)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值