在 Node.js 中處理二進制數據時,我們經常需要操作字節流、文件內容或網絡傳輸的數據。這些數據本質上是二進制形式的,而 JavaScript 原生類型(如字符串、數字)難以直接高效地處理這類數據。此時,Buffer 便成爲了 Node.js 中專門用於處理二進制數據的核心工具。

一、爲什麼需要 Buffer?

在 JavaScript 中,我們可以輕鬆處理文本(如字符串)和數字,但當涉及到二進制數據(例如圖片、音頻文件、網絡傳輸的原始數據包)時,字符串或普通數組就顯得力不從心了。例如:
- 讀取一個圖片文件時,得到的是一連串字節(二進制數據),而非文本;
- 網絡請求中,服務器返回的響應是二進制流(如 JSON 格式的二進制編碼);
- 處理數據庫中的二進制數據(如 BLOB 類型)。

Node.js 的 Buffer 正是爲解決這類問題而生,它提供了高效的二進制數據存儲和操作能力,是 Node.js 處理 I/O 操作(輸入/輸出)的基石。

二、什麼是 Buffer?

Buffer 是 Node.js 中的一個全局對象,專門用於存儲和操作二進制數據。可以將它理解爲一個固定長度的“字節數組”,其中每個元素是 0~255 之間的整數(代表一個字節)。例如,Buffer 可以存儲一張圖片的全部字節,或一段音頻的採樣數據。

Buffer 的核心特點:
- 所有元素都是 0~255 的整數(即一個字節);
- 無法動態擴容,創建時需指定長度;
- 存儲二進制數據,不依賴字符串編碼。

三、創建 Buffer 的幾種方式

在 Node.js 中,創建 Buffer 有多種方法,以下是最常用的幾種:

1. 通過長度創建(初始化爲 0)

使用 Buffer.alloc(size) 方法創建一個指定長度的 Buffer,所有字節初始化爲 0。
例如,創建一個長度爲 5 的 Buffer:

const buf = Buffer.alloc(5); 
console.log(buf); // 輸出: <Buffer 00 00 00 00 00> 
// 此時 Buffer 中每個位置都是 0(對應 ASCII 碼中的空字符)

2. 通過數組創建

使用 Buffer.from(array) 方法,將數組中的元素(0~255 的整數)轉換爲 Buffer。
例如,創建一個包含 [65, 66, 67] 的 Buffer(對應 ASCII 碼 A、B、C):

const buf = Buffer.from([65, 66, 67]); 
console.log(buf); // 輸出: <Buffer 41 42 43> 
// 41 是 A,42 是 B,43 是 C 的十六進制表示

3. 通過字符串創建

使用 Buffer.from(string, encoding) 方法,將字符串轉換爲 Buffer(需指定編碼,如 utf8base64 等)。
例如,將字符串 "hello" 轉換爲 Buffer(默認使用 utf8 編碼):

const buf = Buffer.from("hello"); 
console.log(buf); // 輸出: <Buffer 68 65 6c 6c 6f> 
// 68 是 'h',65 是 'e',依此類推

四、Buffer 的讀寫操作

Buffer 的核心操作是通過索引訪問或修改字節數據,以及獲取長度等基本信息。

1. 訪問與修改數據

Buffer 支持通過索引(從 0 開始)讀取或修改單個字節。每個索引對應一個 0~255 的整數(超過 255 會被截斷,負數會被轉爲正數)。

示例:修改 Buffer 中的第一個字節

const buf = Buffer.from("hello"); 
console.log(buf[0]); // 輸出: 104(對應字符 'h' 的 ASCII 碼)

buf[0] = 72; // 將第一個字節改爲 72(ASCII 碼 'H')
console.log(buf.toString()); // 輸出: "Hello" 
// 原字符串 "hello" 的第一個字符被改爲 'H',變成 "Hello"

2. 查看 Buffer 長度

Buffer 的 length 屬性表示其包含的字節數:

const buf = Buffer.from("hello"); 
console.log(buf.length); // 輸出: 5 
// "hello" 是 5 個字符,每個字符在 UTF-8 中佔 1 字節

3. 遍歷 Buffer 數據

通過 for 循環遍歷 Buffer 的所有字節:

const buf = Buffer.from("abc"); 
for (let i = 0; i < buf.length; i++) { 
  console.log(`第 ${i} 個字節: ${buf[i]}, 字符: ${String.fromCharCode(buf[i])}`); 
}
// 輸出:
// 第 0 個字節: 97, 字符: a
// 第 1 個字節: 98, 字符: b
// 第 2 個字節: 99, 字符: c

五、Buffer 與字符串的轉換

Buffer 最常用的場景之一是與字符串互相轉換,需注意編碼一致性(如 utf8base64hex 等)。

1. Buffer 轉字符串

使用 buf.toString(encoding) 方法,將 Buffer 轉換爲字符串,需指定編碼:

const buf = Buffer.from([72, 101, 108, 108, 111]); // 對應 "Hello" 的 ASCII 碼
console.log(buf.toString("utf8")); // 輸出: "Hello"(默認編碼爲 utf8)
console.log(buf.toString("base64")); // 輸出: "SGVsbG8="(base64 編碼結果)

2. 字符串轉 Buffer

使用 Buffer.from(string, encoding) 方法,將字符串轉換爲 Buffer(默認 utf8 編碼):

const str = "你好,Node.js"; 
const buf = Buffer.from(str, "utf8"); 
console.log(buf.toString("hex")); // 輸出十六進制編碼(如:e4 bd a0 e5 a5 bd ef bc 8c 4e 6f 64 65 2e 6a 73)

3. Buffer 拼接

多個 Buffer 無法直接用 + 拼接,需使用 Buffer.concat([buf1, buf2, ...]) 方法:

const buf1 = Buffer.from("Hello"); 
const buf2 = Buffer.from(" World"); 
const combined = Buffer.concat([buf1, buf2]); 
console.log(combined.toString()); // 輸出: "Hello World"

六、Buffer 的常用方法

除了上述基礎操作,Buffer 還提供了一些實用方法,例如:

1. 寫入字符串到 Buffer

使用 buf.write(string, offset, length, encoding) 方法,將字符串寫入 Buffer(從指定位置開始):

const buf = Buffer.alloc(10); // 創建長度爲 10 的 Buffer(初始爲 0)
buf.write("Hi", 0); // 從偏移量 0 開始寫入 "Hi"(佔 2 字節)
console.log(buf.toString()); // 輸出: "Hi"(剩餘 8 字節爲 0,不影響輸出)

2. 截取部分 Buffer

使用 buf.slice(start, end) 方法,截取 Buffer 的子部分(不修改原 Buffer):

const buf = Buffer.from("abcdef"); 
const sub = buf.slice(1, 4); // 從索引 1 到 3(不包含 4)
console.log(sub.toString()); // 輸出: "bcd"

七、應用場景與注意事項

常見應用場景

  • 文件處理:讀取圖片、視頻等二進制文件時,Buffer 用於存儲文件內容;
  • 網絡通信:HTTP 請求/響應的原始數據通過 Buffer 傳輸和解析;
  • 數據庫操作:處理 BLOB(二進制大對象)類型數據時,Buffer 用於存儲和讀取二進制內容。

注意事項

  • 編碼一致性:轉換字符串時,需確保編碼一致(如 utf8base64 後,必須用 base64 轉回字符串),否則會出現亂碼;
  • 溢出處理:修改 Buffer 時,若賦值超過 255 會被截斷(如 256 → 0,-1 → 255);
  • 內存管理:Buffer 是 Node.js 堆外內存(非 V8 垃圾回收),操作時需注意避免內存泄漏(如大 Buffer 未及時釋放)。

總結

Buffer 是 Node.js 處理二進制數據的核心工具,掌握它的基礎操作(創建、讀寫、轉換)是理解文件、網絡、數據庫等 I/O 操作的關鍵。從簡單的字符串轉 Buffer,到複雜的二進制數據拼接,Buffer 爲我們提供了高效且靈活的二進制處理能力。通過多練習 Buffer 的創建、轉換和拼接,你會逐漸熟悉 Node.js 中處理二進制數據的核心邏輯。

希望這篇入門文章能幫助你快速理解 Buffer 的作用和使用方法!

小夜