這篇要進入到資料的世界,認識Buffer(緩衝)與Stream(串流),讓之後要學的通訊協定及資料傳輸能比較好理解。
Buffer(緩衝)是在資料移動時,提供資料暫存的記憶體位置,可以暫時的累積資料再繼續傳遞,就像在網路上看影片時,會有灰色區塊的緩衝暫存還沒播放到的影片資料。

在NodeJS中的緩衝,是以二進制資料(binary data)的形式暫存資料,可以透過函式如:from或toString進行資料的解碼或編碼,支援的編碼包含常用的utf8與ASCII等,可以參考NodeJS官網的文件說明。
看看例子
new Buffer.from(字串,編碼)可以直接建立新的Buffer,在定義新的Buffer變數時,編碼預設為utf8。let buffer = new Buffer.from("Hello"); //編碼預設為utf8
buffer可以確認Buffer是以二進制資料儲存。console.log(buffer);

toString()的成果,會將Buffer轉成字串印出。console.log(buffer.toString());

toJSON()轉成JSON格式物件,Buffer暫存的資料會以unicode編碼的陣列表現。console.log(buffer.toJSON());

Stream(串流)指的是資料傳遞資料的序列流,用具體一點的物質來說明的話,資料和串流就像河流上漂著的東西和河流,資料會順著串流移動,移動至處理資料的目標,在許多情況下也可能會藉由緩衝先暫存部分順著串流移動的資料,再一併傳遞進行資料處理。

在NodeJS中的串流,作為EventEmitter的子類別,繼承了on()、emit()等方法,而串流根據資料流向的方向不同又分成writable(寫入)、readable(讀取)、duplex(讀寫)、transform(轉換)等類型,每一個串流的類別都繼承串流的方法。從官方的文件也可以發現串流的類別是一個抽象/基底類別(abstract/base class),不會被直接使用,而是透過繼承取用的其屬性及方法,因此必須透過建立新的客製化物件再去繼承基底類別。

實作看看
在開始之前,透過lipsum generator製作一份測試用的文字檔案data.txt。
由於Stream要透過客製化的物件進行繼承,在NodeJS中的fs模組提供了建立客製化Stream的功能,因此需要引用fs模組,再透過createReadStream()建立一個新的讀取串流,在讀取資料時,會先以Buffer的形式暫存。
let fs = require("fs");
let readable = fs.createReadStream(__dirname + "/data.txt"); //__dirname為目前資料夾
on()註冊data事件,以監聽資料讀取的過程,而綁定該事件內容的函式,加入chunk作為讀取資料時的參數,chunk是串流中傳遞的資料片段,透過印出chunk可以確認資料讀取的情況。readable.on("data", function(chunk){
console.log(chunk);
});
chunk二進制成果。
createReadStream()函式中加入編碼,就會以字串印出整份資料。let readable = fs.createReadStream(__dirname + "/data.txt", {encoding: "utf8"});

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);
});

串流(Stream)與緩衝(Buffer)在資料傳遞的概念上很重要,先了解的資料如何移動、暫存的方法,再接下去看到透過通訊傳遞資料的部份時,可以有較深刻的印象。
https://nodejs.org/api/stream.html#stream_stream
https://whien.medium.com/換個角度用生活思考難以理解的串流緩衝區-stream-buffer-66fcb116c70
Learn and Understand NodeJS [課程]