zoukankan      html  css  js  c++  java
  • 可读流与可写流

    可读流模式

    ·内部有flowing(流动)模式和非flowing(暂停)模式来读取数据

    ·flowing模式使用操作系统的内部IO机制来读取数据,并尽可能快的提供数据

    ·非flowing模式时流默认处于暂停模式,必须显示调用read方法来读取数据

      注意:如果没有绑定data事件处理器,并且没有pipe()目标,同时流被切换到流动模式,那么数据会丢失。比如没有绑定data事件,但是触发了resume方法。

    ·如何切换到流动模式

      -添加一个data事件处理器来监听数据

      -调用resume()方法来明确开启数据流

      -调用pipe()方法将数据发送到一个Writable可写流

    ·切换回暂停模式

      -如果没有导流目标,调用pause()方法。

      -如果有导流目标,移除所有data事件处理器,调用unpipe()方法移除所有导流目标

    可读流的事件

      readable:监听readable会使数据从底层读到系统缓存区,读到数据后或者排空后如果再读到数据,会触发readable事件

      data:绑定一个data事件监听器会将流切换到流动模式,数据会被尽可能的读出

      end:该事件会在读完数据后被触发

      error:当数据接收发生错误时触发

      close:当底层数据源(比如:源头的文件描述符)被关闭时触发,并不是所有流都会触发这个事件

    可读流的方法

      read:在readable事件触发时的回调函数里读取数据

      setEncoding:指定编码

      pause:通知对象停止触发data事件

      resume:通知对象恢复触发data事件

      pipe:设置管道,将可读流里的内容导入到参数指定的可写流中

      unpipe:取消数据通道

      unshift:把数据块插回队列开头

    写一个readStream.js:

    var fs = require('fs');
    var rs = fs.createReadStream('./read.txt',{start:0,end:5,encoding:'utf8'})//读取字节始末位置,包前也包后,所以此处读取的是6个字节
    var buffers = [];
    rs.on('readable',function(){//结合highWaterMark使用
      var buff;
      while(null != (buff = rs.read(1))){
        buffers.push(buff);
      }
    })
    rs.on('end',function(data){
      var data = Buffer.concat(buffers)
      console.log('读取完成',data.toString());
    })

     

    可写流模式

    使用各种实现stream.Writable接口的对象来将流数据写入到对象中

      fs.writeStream:写入文件

      http.ClientRequest:客户端请求对象

      http.ServerResponse:http中的响应对象,response.write()

      net.socket:TCP中的socket对象

      process.stdout:标准输出

      process.stderr:错误输出

      Gunzip:解压

    可写流的方法

      -write 写入数据 writable.write(chunk,[encoding],[callback]),其中chunk是写入的数据,为Buffer或者字符串。该方法的返回值为布尔值,系统缓存区定满时为false,未满时为true

      -end 结束写入数据时触发,迫使缓存区中的数据立即写入目标对象,调用后不能再写入

    var fs = require('fs');
    var rs = fs.createReadStream('./read.txt',{start:0,end:5,encoding:'utf8'})//读取字节始末位置,包前也包后,所以此处读取的是6个字节
    var ws = fs.createWriteStream('./write.txt')
    ws.on('open',function(){
      console.log('写入文件已打开');
    })
    rs.on('data',function(data){
      ws.write(data)
    })
    rs.on('end',function(){
      ws.end('写入完成,关闭可写流',function(){
        console.log('写入完毕,共写入%d字节',ws.bytesWritten);
      })
    }) 

    大文件读取流程

      1,从文件读入缓存区并填满

      2,把缓存区的数据写入目标文件,同时读取剩余数据到内存中,write返回false

      3,缓存区中的数据全部写入后触发drain事件

      4,先将内存中的数据写入缓存区,再读取文件剩余数据到缓存区直到填满(只能从缓存区向目标文件写数据)

      5,持续上述步骤,直到完成

    模拟大文件读取流程bigfile.js:

    var fs = require('fs');
    var rs = fs.createReadStream('./big.fbr')//默认是64k,所以尽量选择一个大文件来模拟
    var ws = fs.createWriteStream('./big2.fbr')//默认是16k
    ws.on('open',function(){
      console.log('写入文件已打开');
    })
    rs.on('data',function(data){
      var flag = ws.write(data)
      console.log(flag);
    })
    ws.once('drain',function(){//可写流的缓存区的数据全部写到目标文件时触发
      console.log(drain);
    })

    pipe:将数据的滞留量限制到一个可接受的水平,以使得不同速度的来源和目标不会淹没可用内存

      readStream.pipe(writeStream,[options])

    var fs = require('fs');
    var rs = fs.createReadStream('./big.fbr')//默认是64k,所以尽量选择一个大文件来模拟
    var ws = fs.createWriteStream('./big2.fbr')//默认是16k
    rs.pipe(ws)

    pipe方法的原理为:

    rs.on('data',function(data){
       var flag = ws.write(data) 
       if(!flag){
          rs.pause(); 
       } 
    })
    ws.on('drain',function(){
       rs.resume();
    })
  • 相关阅读:
    Vue.js学习笔记(8)拖放
    Vue.js学习笔记(7)组件详解
    使用了与请求的协议不兼容的地址的解决办法
    修改machine.config遇到System.Net.ServicePointManager 的类型初始值设定项引发异常
    未找到路径“/Agent/SissQrTemplate/AddN”的控制器或该控制器未实现 IController。
    C# .NET 2.0 判断当前程序进程是否为64位运行时 (x64)
    荣耀9开启虚拟按键
    C# .NET 4.5 将多个文件添加到压缩包中
    开IE时 暴卡
    VMware Workstation 安装 mac OS 时遇到 不可恢复错误: (vcpu-0)
  • 原文地址:https://www.cnblogs.com/web-fengmin/p/6398833.html
Copyright © 2011-2022 走看看