在 Stream 篇結中,我們留下了一個問題,下述程式碼輸出的 chunk 是什麼東西?
透過列印,我們發現 chunk 是 Buffer 對象,其中的元素是16進位的兩位數,也就是0~255的數值。 【相關教學推薦:nodejs影片教學、程式設計教學】
#說明在Stream 中流動的資料就是Buffer,那以下就讓我們來探究一下Buffer 的真實面目!
? Node 中為什麼要引入Buffer?
最開始的時候JS 只在瀏覽器端運行,對於Unicode 編碼的字串容易處理,但是對於二進制和非Unicode 編碼的字串處理困難。而二進制是電腦最底層的資料格式,視訊/音訊/程式/網路包都是以二進位來儲存的。所以 Node 需要引入一個物件來操作二進位,因此 Buffer 誕生了,用於 TCP流/檔案系統等操作處理二進位位元組。
由於Buffer 在Node 中過於常用,所以在Node 啟動的時候已經引入了Buffer,無需使用require()
ArrayBuffer 是內存之中的一段二進位數據,本身不能夠操作內存,需要透過TypedArray 物件或DataView 來操作。將緩衝區中的資料表示為特定的格式,並透過這些格式來讀寫緩衝區的內容,其部署了數組接口,可以使用數組的方式來操作資料
最常用的是TypeArray 視圖,用來讀寫簡單類型的ArrayBuffer,例如Uint8Array(無符號8位元整數)陣列視圖, Int16Array(16位元整數)陣列視圖
NodeJS 中的Buffer 類別其實是Uint8Array 的實作。
Buffer 是一個類似Array 的對象,但是它主要用於操作位元組
Buffer 是JS 和C 結合的模組,性能部分都由C 實現,非性能部分都是JS 實現的
Buffer 所佔用的記憶體不是由V8 分配的,屬於堆外記憶體。
Buffer 物件類似數組,其元素為16進位的兩位數,即0~255的數值
#從這個例子能夠看出,不同字元在Buffer 中佔據的位元組是不一樣的,在UTF-8 編碼下,中文佔據3個字節,英文和半角標號佔用1個位元組
? 輸入的元素是小數/負數/超出255會發生什麼事?
對於上述這種情況,Buffer 的處理為:
Buffer 裡面為什麼展示的是16進位
其實在記憶體儲存的依舊是二進制數,只是Buffer 在顯示這內存資料的時候採用了16進位
大小為2位元組的buffer,一共有16 bit ,例如是00000001 00100011
,如果直接這樣顯示不太方便就轉成為了16進位<buffer></buffer>
# 建立固定大小的buffer
分配一個大小為size 位元組的Buffer,allocUnsafe 執行速度比alloc 快,我們發現其結果並不像Buffer.alloc 那樣都初始化為00
#當呼叫allocUnsafe 時分配的記憶體段尚未初始化,這樣分配記憶體速度很塊,但分配到的記憶體片段可能包含舊資料。如果使用的時候不覆寫這些舊資料就可能造成記憶體洩露,雖然速度快,盡量避免使用
Buffer 模組會預先分配一個內部的大小為 Buffer.poolSize 的Buffer 實例,作為快速分配的記憶體池,用於使用allocUnsafe 建立新的Buffer 實例
根據內容直接建立Buffer
Buffer在創建的時候大小就已經被確定了且無法調整!分配小物件如果分配的物件小於8KB,Node 會以小物件的方式來進行分配Buffer 的分配過程中主要使用一個局部變數 pool 作為中間處理對象,處於分配狀態的 slab 單元都指向它。以下是指派一個全新的slab 單元的操作,它將新申請的SlowBuffer 物件指向它 一個slab 單元 分配一個2KB 大小的Buffer建立一個2KB 的buffer後,一個slab 單元記憶體如下: 這個分配過程是由allocate方法完成 當我們建立了一個2KB 的buffer 之後,目前slab 狀態為partial再次建立buffer 的時候,會去判斷目前slab 剩餘空間是否足夠。如果足夠,使用剩餘空間,並更新slab 的分配狀態如果slab 空間不夠,就會建構新的slab,原slab 中剩餘的空間造成浪費分配大物件如果有超過8KB 的buffer,直接會走到creatUnsafeBuffer 函數,分配一個slab 單元,這個slab 單元將會被這個大Buffer 物件獨佔allocate 分配機制如圖 #Buffer 的記憶體分配機制 #Buffer 和字元編碼透過使用字元編碼,可實現Buffer 實例與JavaScript 字串之間的相互轉換
Node 中目前支援utf8、ucs2、utf16le、latin1、ascii、base64、hex、base64Url 八種編碼方式,具體實作
#針對於每一種不同的編碼方案都會用實作一系列api,傳回會有不同的結果,Node.js 會根據傳入的encoding 來傳回不同的物件
主要透過上述講的Buffer.from 方法,預設的encoding 方式為utf-8
#? 為什麼會出現亂碼呢?如何解決這個問題呢?
按著讀取來說,我們每次讀取的長度為4,chunk輸出如下
#對於data = chunk
等價於data = data.toString chunk.toString
#由於一個中文佔據三個字節,第一個chunk 中的第四個位元組會顯示亂碼,第二個chunk 的第一第二個位元組也無法形成文字等等,所以會展示亂碼問題
更多node相關知識,請造訪:nodejs 教學!
以上是深入了解Node中的Buffer的詳細內容。更多資訊請關注PHP中文網其他相關文章!