Day9 NodeJS-Buffer与Stream

这篇要进入到资料的世界,认识Buffer(缓冲)与Stream(串流),让之後要学的通讯协定及资料传输能比较好理解。

Buffer

Buffer(缓冲)是在资料移动时,提供资料暂存的记忆体位置,可以暂时的累积资料再继续传递,就像在网路上看影片时,会有灰色区块的缓冲暂存还没播放到的影片资料。

https://ithelp.ithome.com.tw/upload/images/20210924/20139980wwuc4Ihg1q.jpg

在NodeJS中的缓冲,是以二进制资料(binary data)的形式暂存资料,可以透过函式如:fromtoString进行资料的解码或编码,支援的编码包含常用的utf8ASCII等,可以参考NodeJS官网的文件说明。

看看例子

  1. 由於Buffer在资料串流上经常使用,因此NodeJS将Buffer定义为全域参数,不需再另外引用,以new Buffer.from(字串,编码)可以直接建立新的Buffer,在定义新的Buffer变数时,编码预设为utf8
let buffer = new Buffer.from("Hello");		//编码预设为utf8
  1. 直接印出buffer可以确认Buffer是以二进制资料储存。
console.log(buffer);

https://ithelp.ithome.com.tw/upload/images/20210924/20139980GeTls6U7gq.png

  1. 另外尝试印出使用toString()的成果,会将Buffer转成字串印出。
console.log(buffer.toString());

https://ithelp.ithome.com.tw/upload/images/20210924/20139980pJCeCYWTsU.png

  1. 除了字串也可以透过toJSON()转成JSON格式物件,Buffer暂存的资料会以unicode编码的阵列表现。
console.log(buffer.toJSON());

https://ithelp.ithome.com.tw/upload/images/20210924/20139980Y5WKATMlDU.png

Stream

Stream(串流)指的是资料传递资料的序列流,用具体一点的物质来说明的话,资料和串流就像河流上漂着的东西和河流,资料会顺着串流移动,移动至处理资料的目标,在许多情况下也可能会藉由缓冲先暂存部分顺着串流移动的资料,再一并传递进行资料处理。

https://ithelp.ithome.com.tw/upload/images/20210924/201399800lNjzL9wab.jpg

在NodeJS中的串流,作为EventEmitter的子类别,继承了on()emit()等方法,而串流根据资料流向的方向不同又分成writable(写入)、readable(读取)、duplex(读写)、transform(转换)等类型,每一个串流的类别都继承串流的方法。从官方的文件也可以发现串流的类别是一个抽象/基底类别(abstract/base class),不会被直接使用,而是透过继承取用的其属性及方法,因此必须透过建立新的客制化物件再去继承基底类别。

https://ithelp.ithome.com.tw/upload/images/20210924/20139980ytbNGsxSha.jpg

实作看看

  1. 在开始之前,透过lipsum generator制作一份测试用的文字档案data.txt

  2. 由於Stream要透过客制化的物件进行继承,在NodeJS中的fs模组提供了建立客制化Stream的功能,因此需要引用fs模组,再透过createReadStream()建立一个新的读取串流,在读取资料时,会先以Buffer的形式暂存。

let fs = require("fs");

let readable = fs.createReadStream(__dirname + "/data.txt");	//__dirname为目前资料夹
  1. 使用on()注册data事件,以监听资料读取的过程,而绑定该事件内容的函式,加入chunk作为读取资料时的参数,chunk是串流中传递的资料片段,透过印出chunk可以确认资料读取的情况。
readable.on("data", function(chunk){
  console.log(chunk);
});
  1. 执行除错後,由於Stream中的Buffer尺寸预设为64KB,因此一次性的印出大小61150bytes的chunk二进制成果。

https://ithelp.ithome.com.tw/upload/images/20210924/20139980k1nzOLSS9W.png

  1. 若想以字串的形式检视成果,可以在createReadStream()函式中加入编码,就会以字串印出整份资料。
let readable = fs.createReadStream(__dirname + "/data.txt", {encoding: "utf8"});

https://ithelp.ithome.com.tw/upload/images/20210924/2013998005BueTRbPd.png

  1. Buffer的大小也可透过highWaterMark设定,单位为bytes。这边以32KB作为例子,另外将印出的资讯改为chunk.length确认资料是否因Buffer尺寸变动而分段。
let readable = fs.createReadStream(__dirname + "/data.txt", {encoding: "utf8", highWaterMark: 32*1024});

readable.on("data", function(chunk){
  console.log(chunk.length);
});

https://ithelp.ithome.com.tw/upload/images/20210924/20139980jOPSZAIVo9.png

小结

串流(Stream)与缓冲(Buffer)在资料传递的概念上很重要,先了解的资料如何移动、暂存的方法,再接下去看到透过通讯传递资料的部份时,可以有较深刻的印象。

参考资料

https://nodejs.org/api/stream.html#stream_stream

https://whien.medium.com/换个角度用生活思考难以理解的串流缓冲区-stream-buffer-66fcb116c70

Learn and Understand NodeJS [课程]


<<:  【Side Project】 菜单内容(建立资料库)

>>:  【DAY 10】SharePoint 的应用五花八门,什麽最适合你?(下)

Unity自主学习(五):Unity安装失败如何解决

昨天我们用Unity Hub安装了Unity引擎,顺利的话就能安装成功 但还是有机会遇到安装失败的情...

Day 3:安装 Hexo 前置作业:Node.js、Git、网页编辑器 VS code、文章编辑器 Typora

在架设 Hexo 之前,有些前置作业要先进行。其中由於 Hexo 是使用 Node.js 撰写,并且...

实战操作 - 鸿海 2317

鸿海是我个人主要标的之一,趁星期五(10/1)指数大跌,趁机再次加码。 主要大量进场时间点是在去年底...

27. Tech leader的重要战略

前言 这篇的讲者很nice,直接讲了这篇演讲很适合给这几种人看 刚成为TL 还不是TL但你觉得你会...

Material UI in React [Day9] Inputs (Radio) 单选 & (Switch) 开关

Radio 当用户需要查看所有可用选项时使用单选按钮,如果可用选项可以折叠,请考虑使用下拉菜单(Se...