关于Node的学习之Buffer\Stream

简单理解:

我们可以把整个流(stream)和 buffer 的配合过程看作公交站。在一些公交站,公车在没有装满乘客前是不会发车的,或者在特定的时刻才会发车。当然,乘客也可能在不同的时间,人流量大小也会有所不同,有人多的时候,有人少的时候,乘客或公交站都无法控制人流量。不论何时,早到的乘客都必须等待,直到公车接到指令可以发车。当乘客到站,发现公车已经装满,或者已经开走,他就必须等待下一班车次。

典型的例子:

就是你在线看视频的时候。如果你的网络足够快,数据流(stream)就可以足够快,可以让 buffer 迅速填满然后发送和处理,然后处理另一个,再发送,再另一个,再发送,然后整个 stream 完成。

但是当你网络连接很慢,当处理完当前的数据后,你的播放器就会暂停,或出现”缓冲”(buffer)字样,意思是正在收集更多的数据,或者等待更多的数据到来,才能下一步处理。当buffer装满并处理好,播放器就会显示数据,也就是播放视频了。在播放当前内容的时候,更多的数据也会源源不断的传输、到达和在 buffer 等待。

一、Buffer概念:

在网络通信中,拿前端举例,客户端发送请求给服务器请求index.html,则服务器会以字符串的形式返回给客户端html文件,但是像mp3、flv、mp4这些媒体文件实际上是二进制数据文件,所以当客户端请求时,服务器必须分块以二进制的形式给客户端发送数据,传统的Array数据类型不足以储存这些数据,Buffer就是为了弥补Array而产生的。

  Buffer就是缓冲区,用来存储数据的容器,操作和数组类似,js中对于数组的操作很多都可以使用,它的每个元素储存2位16进制的数据,一个元素就代表内存的一个字节(简化一下就是:buffer 能够与二进制数据流进行交互操作。)

Buffer不需要引入可以直接使用

在这里插入图片描述
捋一下:

  1. Buffer是在内存中开辟一段空间用来存储数据的
  2. 数据都是二进制的

二、Stream概念:

流(stream)在 Node.js 中是处理流数据的抽象接口(abstract interface)。 stream 模块提供了基础的 API 。使用这些 API 可以很容易地来构建实现流接口的对象。

   流(stream)就是一系列从A点到B点移动的数据,完整点的说,就是当你有一个很大的数据需要传输、搬运时,你不需要等待所有数据都传输完成才开始下一步工作。

实际上,大型数据会被分割成小块(chunks)进行传输。所以,buffer 的原始定义中所说的(“streams of binary data… in the context of… file system”)意思就是说二进制数据在文件系统中的传输。比如,将 file1.txt 的文字存储到 file2.txt 中。

捋一下:

  • Stream的三大原则:有源头、有终点、源头流向终点
  • Stream就像老司机,将装着数据的Buffer开向终点

特性:流是可读的、可写的,或是可读写的。

4种流类型:

  • Readable - 可读的流(fs.createReadStream())
  • Writable -可写的流(fs.createWriteStream())
  • Duplex - 可读写的流(net.Socket)
  • Transform -在读写过程中可以修改和变换数据的 Duplex 流 (例如 zlib.createDeflate())

所有的 Stream 对象都是 EventEmitter 的实例。常用的事件有:

  • data - 当有数据可读时触发
  • end - 没有更多的数据可读时触发
  • error - 在接收和写入过程中发生错误时触发
  • finish - 所有数据已被写入到底层系统时触发
### BufferStream 使用方法及应用场景 BufferStream 是一种用于处理缓冲区数据的流对象,在 Node.js 环境下尤为常见。通过 BufferStream,程序能够高效地管理二进制数据传输过程中的缓存操作。 #### 创建与初始化 为了创建一个基于 `Buffer` 对象的可写流实例,通常会利用第三方库如 `buffer-stream` 或者自定义实现类似的逻辑功能。下面是一个简单例子展示如何构建并使用此类流: ```javascript const { Writable } = require('stream'); class BufferWritable extends Writable { constructor(options) { super({ decodeStrings: false, ...options }); this.buffer = []; } _write(chunk, encoding, callback) { this.buffer.push(chunk); callback(); } } // 实例化 BufferWritable 流 let bw = new BufferWritable(); bw.on('finish', () => { console.log(Buffer.concat(bw.buffer)); }); ``` 此代码片段展示了怎样继承内置模块 `stream.Writable` 来制作自己的 `BufferWritable` 类[^1]。当向该类的对象中写入数据时,这些数据会被追加到内部数组里;一旦触发 `'finish'` 事件,则将所有累积的数据块连接成单个完整的 `Buffer` 并打印出来。 #### 应用场景 - **文件上传下载**:在网络应用中经常遇到大文件传输的需求,此时采用分片方式并通过 BufferStream 处理每一部分可以有效降低内存占用率。 - **实时日志记录**:对于需要持续监控的服务端应用程序来说,借助于 BufferStream 能够及时收集运行期间产生的各类信息而不必担心丢失任何一条重要通知。 - **多媒体编码解码**:音视频编解码器往往涉及大量原始音频帧或图像像素点的操作,运用 BufferStream 可简化这类密集型计算任务之间的衔接工作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值