node官网API总结--Buffer、Stream

332 阅读5分钟
看完这篇文章,你需要能解答以下问题:
1. buffer是什么?为什么要引入Buffer?
2. Stream用于处理什么?有哪些方法、API
    stream是对buffer的高级封装,操作的底层还是buffer对象
    stream继承自EventEmitter接口,可以实现对读写操作的监听

推荐阅读

buffer和stream的区别

  • 二进制数据
    • 计算中的数据类型,比如文字、图片、视频等,都是以0、1的形式存储在内存中。
  • 字符集
    • 定义一套规则,用数字表示常用的字符
    • 常用的规则有:ASCII和 Unicode编码
  • 字符编码
    • 定义一套规则,规定如何用二进制形式,表示数字,即用多少位来表示数字,比如UTF-8
    • utf-8规定用字节表示数据,一个字节用8位(bit)表示,即用8个0或1,表示一个字节
  • stream
    • 数据流,可以将数据分成块传输
  • buffer
    • 等待区域—buffer,电脑中很小的一个物理地址,一般在内存中,数据在这里暂存
    • 最后,在stream中,发送出去并处理
    • 因此buffer,可以在stream中,对数据进行处理

Buffer:缓冲器

基础介绍

  • Buffer在全局作用域中,无需使用require()
  • Node无法操作二进制数据,因此无法直接对内存进行读写。
    • JS只有字符串类型,没有二进制数据类型,因此Node提供和String对等的全局钩子函数Buffer实现对二进制数据的操作
      • 读取文件,能够得到Buffer实例
      • 也可以直接构造Buffernew Buffer()
  • Buffer解决Node支持二进制数据的问题,可以让node处理内存,如操作数据流、文件系统等
  • 新版本Node中,创建BufferAPI:new Buffer()已经不被推荐使用了,改用 Buffer.from(array)
  • 用途:让Node以数据流形式读取内存中的数据
    • 数据流 一般不能一次性获取到,因此适合大数据的读取和不断返回chunk的外部源。
    • 流的生产速度和消费者速度通常是不一致的,因此需要buffer暂存数据。

Buffer和字符串的转换

Buffer.from(str, ‘utf8’):字符串 ===> Buffer
buf.toString(‘utf8’): Buffer ===> string
buf.toJSON():Buffer ==> json
  • 默认字符编码格式
    • 字符编码
      • 解码:Buffer转换为字符串
      • 编码:字符串转换为Buffer
    • 二进制转文本的编码:base64、hex
      • 编码:Buffer转换为字符串
      • 解码:字符串转换为Buffer
  • Buffer实例也是JS的Uint8Array和 TypedArray实例,但有某些细微的不兼容

常用API

* 创建buffer
    * Buffer.from()
    * Buffer.alloc() | allocUnsafe() | allocUnsafeSlow
        * alloc():默认用0填充,速度比其他两个慢,但也较为安全
        * allocUnsafe:默认用之前预留的内存分配数据
* buffer格式转换
    * buf.toJSON()
    * buf.toString()
* 拷贝buffer
    * buf.copy(target, targetStart, sourceStart, sourceEnd) === TypedArray.set
    * copy():先创建新内存,然后将内存中的数据拷贝过去
* 裁剪buffer
    * buf.slice()
    * String是只读的,对字符串的改变,都是会得到一个新字符串
    * 但Buffer是指针,更改某个位置的字节或slice()方法不会生成一个新Buffer,而是返回一个更改后的原Buffer
        * Buffer.slice()不会返回一个新buffer,而是返回修改了后的原buffer指针
* buffer相等性判断:buf1.equals(buf2)
* 判断buffer是否包含特定值:includes、indexOf
* 清除Buffer:Buffer.fill(0)
* 释放buffer:buffer无法自动释放,只能靠V8的垃圾回收机制,但是我们可以解除对buffer的引用

Stream

  • 处理Node中的流式数据,如http服务器的请求和 process.stdout都是流式数据
  • Stream()操作,是基于事件机制的,继承自NodeJS提供的EventEmitter

流的类型—4种

  • Writeable:可写数据流
  • Readable:可读数据流
  • Duplex:可写可读流
  • Transform:读写过程中,可以互相转换的数据流

流操作的三种形式

  • String | Buffer | 对象模式(除String外的其他类型,统称为对象模式)
  • 将已经存在的流,切换为对象模式是不安全的。
  • 可以利用objectMode选项,将流实例,切换为对象模式

缓冲

  • 缓冲器中存在可写流和可读流,可利用writeable.writeableBuffer和 readable.readableBuffer获取
  • highWateMark:缓冲器中可缓冲的数据大小,由流构造函数决定
    • 普通模式的流:highWateMark--指定了字节总数
    • 对象模式:highWateMark—指定对象总数
  • 可读流
    • stream.push():数据会被缓冲在可读流中
    • stream.read():消费可读流
    • 当达到highWateMark的阈值时,流会停止从底层资源读取数据,直到当前缓冲的数据被消费
  • 可写流
    • writeable.wrte()时:数据会被缓冲在可写流中
    • 当highWateMark达到阈值时,调用writeable.write()方法会返回false,否则返回true
  • Stream.pipe():解决写入和读取速度不一致时,造成的爆仓问题
  • Duplex和Transform:各自维护这两个相隔独立的内部缓冲器,用于读取和写入。两边都可以独立运作
    • 如net.Socket就是 Duplex流

消费流

  • 可写流:比如http请求,http的响应
    • 方法:write() | end()
    • 事件:close | finish | error | drain | pipe | unpipe
  • 可读流
    • 方法:destroy() | pause() | pipe() | read() | resume()
    • 事件:close | data | end | pause | resume
  • 当写入速度跟不上读取速度时,只写数据流内部的缓存会爆仓
    • .write()方法返回boolean值判断传入的数据,是写入目标,还是临时放入缓存了
    • .drain()事件判断只写数据流已经将缓存中的数据写入目标,可以继续工作了
    • .resume()继续传递数据
    • .pipe()方法可以直接解决上面的爆仓问题,pipe的内部实现方式和上面的代码类似
  • 双工流和转换流

实现流--待补充

  • 可写流
  • 可读流
  • 双工流和转换流