Node.js Buffer使用詳解


一,開篇分析

NodeJS的開發語言是JavaScript,JavaScript語言自身只有字符串數據類型,沒有二進制數據類型。NodeJS有時會進行網絡傳輸、文件操作、圖片處理等操作,而這些操作都與二進制數據緊密相關。因此,NodeJS提供了一個與String對等的全局構造函數Buffer來提供對二進制數據的操作。在 Node.js中Buffer 類用來創建一個專門存放二進制數據的緩存區。除了可以讀取文件等操作得到Buffer的實例外,還能夠直接構造。

二、創建 Buffer 類

Buffer 提供了以下 API 來創建 Buffer 類:

  • Buffer.alloc(size[, fill[, encoding]]): 返回一個指定大小的 Buffer 實例,如果沒有設置 fill,則默認填滿 0
  • Buffer.allocUnsafe(size): 返回一個指定大小的 Buffer 實例,但是它不會被初始化,所以它可能包含敏感的數據
  • Buffer.allocUnsafeSlow(size)
  • Buffer.from(array): 返回一個被 array 的值初始化的新的 Buffer 實例(傳入的 array 的元素只能是數字,不然就會自動被 0 覆蓋)
  • Buffer.from(arrayBuffer[, byteOffset[, length]]): 返回一個新建的與給定的 ArrayBuffer 共享同一內存的 Buffer。
  • Buffer.from(buffer): 復制傳入的 Buffer 實例的數據,並返回一個新的 Buffer 實例
  • Buffer.from(string[, encoding]): 返回一個被 string 的值初始化的新的 Buffer 實例
// 創建一個長度為 10、且用 0 填充的 Buffer。
const buf1 = Buffer.alloc(10);

// 創建一個長度為 10、且用 0x1 填充的 Buffer。 
const buf2 = Buffer.alloc(10, 1);

// 創建一個長度為 10、且未初始化的 Buffer。
// 這個方法比調用 Buffer.alloc() 更快,
// 但返回的 Buffer 實例可能包含舊數據,
// 因此需要使用 fill() 或 write() 重寫。
const buf3 = Buffer.allocUnsafe(10);

// 創建一個包含 [0x1, 0x2, 0x3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

// 創建一個包含 UTF-8 字節 [0x74, 0xc3, 0xa9, 0x73, 0x74] 的 Buffer。
const buf5 = Buffer.from('tést');

// 創建一個包含 Latin-1 字節 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('tést', 'latin1');

三、寫入緩沖區

語法

寫入 Node 緩沖區的語法如下所示:

buf.write(string[, offset[, length]][, encoding])

參數

參數描述如下:

string - 寫入緩沖區的字符串。

offset - 緩沖區開始寫入的索引值,默認為 0 。

length - 寫入的字節數,默認為 buffer.length

encoding - 使用的編碼。默認為 'utf8' 。

根據 encoding 的字符編碼寫入 string 到 buf 中的 offset 位置。 length 參數是寫入的字節數。 如果 buf 沒有足夠的空間保存整個字符串,則只會寫入 string 的一部分。 只部分解碼的字符不會被寫入。

返回值

返回實際寫入的大小。如果 buffer 空間不足, 則只會寫入部分字符串。

實例

buf = Buffer.alloc(256); len = buf.write("www.runoob.com"); console.log("寫入字節數 : "+ len);

執行以上代碼,輸出結果為:

$node main.js
寫入字節數 : 14

四、從緩沖區讀取數據

語法

讀取 Node 緩沖區數據的語法如下所示:

buf.toString([encoding[, start[, end]]])

參數

參數描述如下:

encoding - 使用的編碼。默認為 'utf8' 。

start - 指定開始讀取的索引位置,默認為 0。

end - 結束位置,默認為緩沖區的末尾。

返回值

解碼緩沖區數據並使用指定的編碼返回字符串。

實例

buf = Buffer.alloc(26); for (var i = 0 ; i < 26 ; i++) { buf[i] = i + 97; } console.log( buf.toString('ascii')); // 輸出: abcdefghijklmnopqrstuvwxyz console.log( buf.toString('ascii',0,5)); //使用 'ascii' 編碼, 並輸出: abcde console.log( buf.toString('utf8',0,5)); // 使用 'utf8' 編碼, 並輸出: abcde console.log( buf.toString(undefined,0,5)); // 使用默認的 'utf8' 編碼, 並輸出: abcde

執行以上代碼,輸出結果為:

$ node main.js
abcdefghijklmnopqrstuvwxyz
abcde
abcde
abcde

五、將 Buffer 轉換為 JSON 對象

語法

將 Node Buffer 轉換為 JSON 對象的函數語法格式如下:

buf.toJSON()

當字符串化一個 Buffer 實例時,JSON.stringify() 會隱式地調用該 toJSON()。

返回值

返回 JSON 對象。

實例

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]); const json = JSON.stringify(buf); // 輸出: {"type":"Buffer","data":[1,2,3,4,5]} console.log(json); const copy = JSON.parse(json, (key, value) => {   return value && value.type === 'Buffer' ?     Buffer.from(value.data) :     value; }); // 輸出: <Buffer 01 02 03 04 05> console.log(copy);

執行以上代碼,輸出結果為:

{"type":"Buffer","data":[1,2,3,4,5]} <Buffer 01 02 03 04 05>

六、聊聊Buffer

JavaScript對字符串處理十分友好,無論是寬字節還是單字節字符串,都被認為是一個字符串。Node中需要處理網絡協議、操作數據庫、處理圖片、文件上傳等,還需要處理大量二進制數據,自帶的字符串遠不能滿足這些要求,因此Buffer應運而生。

Buffer結構

Buffer是一個典型的Javascript和C++結合的模塊,性能相關部分用C++實現,非性能相關部分用javascript實現。

Node在進程啟動時Buffer就已經加裝進入內存,並將其放入全局對象,因此無需require

Buffer對象:類似於數組,其元素是16進制的兩位數。

Buffer內存分配

Buffer對象的內存分配不是在V8的堆內存中,在Node的C++層面實現內存的申請。

為了高效的使用申請來得內存,Node中采用slab分配機制,slab是一種動態內存管理機制,應用各種*nix操作系統。slab有三種狀態:

(1) full:完全分配狀態

(2) partial:部分分配狀態

(3) empty:沒有被分配狀態

七、總結

(1)JavaScript適合處理Unicode編碼數據,但對二進制數據的處理並不友好。

(2)所以處理TCP流或文件系統時,對八位字節流的處理很有必要。

(3)Node有幾個用於處理,創建和消耗八位字節流的方法。

(4)原始數據存放在一個Buffer實例中,一個Buffer類似一個整數數組,但是它的內存,分配在V8堆棧外。一個Buffer的大小是不能更改的。

(5)處理的編碼類型有:ascii,utf8,utf16le,ucs2(utf16le的別名),base64,binary,hex。

(6)Buffer為全局元素,直接new Buffer()就得到一個Buffer實例。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM