搜尋
首頁web前端js教程深入了解Node中的Buffer
深入了解Node中的BufferApr 25, 2023 pm 07:49 PM
前端node.js

深入了解Node中的Buffer

在 Stream 篇結中,我們留下了一個問題,下述程式碼輸出的 chunk 是什麼東西?

深入了解Node中的Buffer

透過列印,我們發現 chunk 是 Buffer 對象,其中的元素是16進位的兩位數,也就是0~255的數值。 【相關教學推薦:nodejs影片教學程式設計教學

Untitled 1.png

#說明在Stream 中流動的資料就是Buffer,那以下就讓我們來探究一下Buffer 的真實面目!

? Node 中為什麼要引入Buffer?

最開始的時候JS 只在瀏覽器端運行,對於Unicode 編碼的字串容易處理,但是對於二進制和非Unicode 編碼的字串處理困難。而二進制是電腦最底層的資料格式,視訊/音訊/程式/網路包都是以二進位來儲存的。所以 Node 需要引入一個物件來操作二進位,因此 Buffer 誕生了,用於 TCP流/檔案系統等操作處理二進位位元組。

由於Buffer 在Node 中過於常用,所以在Node 啟動的時候已經引入了Buffer,無需使用require()

ArrayBuffer

是什麼

ArrayBuffer 是內存之中的一段二進位數據,本身不能夠操作內存,需要透過TypedArray 物件DataView 來操作。將緩衝區中的資料表示為特定的格式,並透過這些格式來讀寫緩衝區的內容,其部署了數組接口,可以使用數組的方式來操作資料

TypedArray 視圖

最常用的是TypeArray 視圖,用來讀寫簡單類型的ArrayBuffer,例如Uint8Array(無符號8位元整數)陣列視圖, Int16Array(16位元整數)陣列視圖

和Buffer 的關係

NodeJS 中的Buffer 類別其實是Uint8Array 的實作。

Buffer 結構

Buffer 是一個類似Array 的對象,但是它主要用於操作位元組

模組結構

Buffer 是JS 和C 結合的模組,性能部分都由C 實現,非性能部分都是JS 實現的Untitled 2.png

Buffer 所佔用的記憶體不是由V8 分配的,屬於堆外記憶體。

物件結構

Buffer 物件類似數組,其元素為16進位的兩位數,即0~255的數值

Untitled 3.png

#從這個例子能夠看出,不同字元在Buffer 中佔據的位元組是不一樣的,在UTF-8 編碼下,中文佔據3個字節,英文和半角標號佔用1個位元組

? 輸入的元素是小數/負數/超出255會發生什麼事?

Untitled 4.png

對於上述這種情況,Buffer 的處理為:

  • 給元素的賦值小於0, 就將該值逐次加256,直到得到一個0到255之間的整數
  • 如果得到的數值大於255,就逐次減256,直到得到0~255區間內的數值
  • 如果是小數,只保留整數部分

Buffer 裡面為什麼展示的是16進位

其實在記憶體儲存的依舊是二進制數,只是Buffer 在顯示這內存資料的時候採用了16進位

大小為2位元組的buffer,一共有16 bit ,例如是00000001 00100011,如果直接這樣顯示不太方便就轉成為了16進位<buffer></buffer>

Buffer 的建立

Buffer.alloc 與Buffer.allocUnsafe

# 建立固定大小的buffer

Buffer.alloc(size [, fill [, encoding]])

  • size 新 Buffer 的所需長度
  • fill 用於預先填入新 Buffer 的值。預設值: 0
  • encoding 如果 fill 是一個字串,則這是它的字元編碼。預設值: utf8

Untitled 5.png

Buffer.allocUnsafe(size)

分配一個大小為size 位元組的Buffer,allocUnsafe 執行速度比alloc 快,我們發現其結果並不像Buffer.alloc 那樣都初始化為00

Untitled 6.png

#當呼叫allocUnsafe 時分配的記憶體段尚未初始化,這樣分配記憶體速度很塊,但分配到的記憶體片段可能包含舊資料。如果使用的時候不覆寫這些舊資料就可能造成記憶體洩露,雖然速度快,盡量避免使用

Buffer 模組會預先分配一個內部的大小為 Buffer.poolSize 的Buffer 實例,作為快速分配的記憶體池,用於使用allocUnsafe 建立新的Buffer 實例

Buffer.from

根據內容直接建立Buffer

  • Buffer.from(string [, encoding] )
  • Buffer.from(array)
  • Buffer.from(buffer)

Untitled 7.png

##Buffer.allocUnsafe 的記憶體機制

為了有效地使用申請來的內存,Node.js 採用了slab 機制進行預先申請、事後分配,是一種動態的管理機制

使用 Buffer.alloc(size) 傳入一個指定的 size 就會申請一塊固定大小的記憶體區域,slab 有以下三種狀態

    full: 完全分配狀態
  • partial:部分分配狀態
  • # empty:沒有被指派狀態
Node.js 使用8 KB 為界限來區分是小物件還是大物件

Untitled 8.png

Buffer在創建的時候大小就已經被確定了且無法調整!

分配小物件

如果分配的物件小於8KB,Node 會以小物件的方式來進行分配

Buffer 的分配過程中主要使用一個局部變數 pool 作為中間處理對象,處於分配狀態的 slab 單元都指向它。以下是指派一個全新的slab 單元的操作,它將新申請的SlowBuffer 物件指向它

Untitled 9.png

一個slab 單元

Untitled 10.png

分配一個2KB 大小的Buffer

建立一個2KB 的buffer後,一個slab 單元記憶體如下:

Untitled 11.png

這個分配過程是由allocate方法完成

Untitled 12.png

當我們建立了一個2KB 的buffer 之後,目前slab 狀態為partial

再次建立buffer 的時候,會去判斷目前slab 剩餘空間是否足夠。如果足夠,使用剩餘空間,並更新slab 的分配狀態

如果slab 空間不夠,就會建構新的slab,原slab 中剩餘的空間造成浪費

分配大物件

如果有超過8KB 的buffer,直接會走到creatUnsafeBuffer 函數,分配一個slab 單元,這個slab 單元將會被這個大Buffer 物件獨佔

allocate 分配機制如圖

Untitled 13.png

#Buffer 的記憶體分配機制

Untitled 14.png

#Buffer 和字元編碼

透過使用字元編碼,可實現Buffer 實例與JavaScript 字串之間的相互轉換

Untitled 15.png

Node 中目前支援utf8、ucs2、utf16le、latin1、ascii、base64、hex、base64Url 八種編碼方式,具體實作

Untitled 16.png

#針對於每一種不同的編碼方案都會用實作一系列api,傳回會有不同的結果,Node.js 會根據傳入的encoding 來傳回不同的物件

Buffer 和字串的轉換

字串轉Buffer

主要透過上述講的Buffer.from 方法,預設的encoding 方式為utf-8

Buffer 轉字串

Untitled 17.png

#? 為什麼會出現亂碼呢?如何解決這個問題呢?

按著讀取來說,我們每次讀取的長度為4,chunk輸出如下

Untitled 18.png

#對於data = chunk等價於data = data.toString chunk.toString

#由於一個中文佔據三個字節,第一個chunk 中的第四個位元組會顯示亂碼,第二個chunk 的第一第二個位元組也無法形成文字等等,所以會展示亂碼問題

更多node相關知識,請造訪:nodejs 教學

以上是深入了解Node中的Buffer的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:掘金社区。如有侵權,請聯絡admin@php.cn刪除
巧用CSS实现各种奇形怪状按钮(附代码)巧用CSS实现各种奇形怪状按钮(附代码)Jul 19, 2022 am 11:28 AM

本篇文章带大家看看怎么使用 CSS 轻松实现高频出现的各类奇形怪状按钮,希望对大家有所帮助!

5个常见的JavaScript内存错误5个常见的JavaScript内存错误Aug 25, 2022 am 10:27 AM

JavaScript 不提供任何内存管理操作。相反,内存由 JavaScript VM 通过内存回收过程管理,该过程称为垃圾收集。

实战:vscode中开发一个支持vue文件跳转到定义的插件实战:vscode中开发一个支持vue文件跳转到定义的插件Nov 16, 2022 pm 08:43 PM

vscode自身是支持vue文件组件跳转到定义的,但是支持的力度是非常弱的。我们在vue-cli的配置的下,可以写很多灵活的用法,这样可以提升我们的生产效率。但是正是这些灵活的写法,导致了vscode自身提供的功能无法支持跳转到文件定义。为了兼容这些灵活的写法,提高工作效率,所以写了一个vscode支持vue文件跳转到定义的插件。

Node.js 19正式发布,聊聊它的 6 大特性!Node.js 19正式发布,聊聊它的 6 大特性!Nov 16, 2022 pm 08:34 PM

Node 19已正式发布,下面本篇文章就来带大家详解了解一下Node.js 19的 6 大特性,希望对大家有所帮助!

浅析Vue3动态组件怎么进行异常处理浅析Vue3动态组件怎么进行异常处理Dec 02, 2022 pm 09:11 PM

Vue3动态组件怎么进行异常处理?下面本篇文章带大家聊聊Vue3 动态组件异常处理的方法,希望对大家有所帮助!

聊聊如何选择一个最好的Node.js Docker镜像?聊聊如何选择一个最好的Node.js Docker镜像?Dec 13, 2022 pm 08:00 PM

选择一个Node​的Docker镜像看起来像是一件小事,但是镜像的大小和潜在漏洞可能会对你的CI/CD流程和安全造成重大的影响。那我们如何选择一个最好Node.js Docker镜像呢?

聊聊Node.js中的 GC (垃圾回收)机制聊聊Node.js中的 GC (垃圾回收)机制Nov 29, 2022 pm 08:44 PM

Node.js 是如何做 GC (垃圾回收)的?下面本篇文章就来带大家了解一下。

【6大类】实用的前端处理文件的工具库,快来收藏吧!【6大类】实用的前端处理文件的工具库,快来收藏吧!Jul 15, 2022 pm 02:58 PM

本篇文章给大家整理和分享几个前端文件处理相关的实用工具库,共分成6大类一一介绍给大家,希望对大家有所帮助。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前By尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
4 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

MantisBT

MantisBT

Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)