在 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(需指定編碼,如 utf8、base64 等)。
例如,將字符串 "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 最常用的場景之一是與字符串互相轉換,需注意編碼一致性(如 utf8、base64、hex 等)。
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 用於存儲和讀取二進制內容。
注意事項¶
- 編碼一致性:轉換字符串時,需確保編碼一致(如
utf8轉base64後,必須用base64轉回字符串),否則會出現亂碼; - 溢出處理:修改 Buffer 時,若賦值超過 255 會被截斷(如 256 → 0,-1 → 255);
- 內存管理:Buffer 是 Node.js 堆外內存(非 V8 垃圾回收),操作時需注意避免內存泄漏(如大 Buffer 未及時釋放)。
總結¶
Buffer 是 Node.js 處理二進制數據的核心工具,掌握它的基礎操作(創建、讀寫、轉換)是理解文件、網絡、數據庫等 I/O 操作的關鍵。從簡單的字符串轉 Buffer,到複雜的二進制數據拼接,Buffer 爲我們提供了高效且靈活的二進制處理能力。通過多練習 Buffer 的創建、轉換和拼接,你會逐漸熟悉 Node.js 中處理二進制數據的核心邏輯。
希望這篇入門文章能幫助你快速理解 Buffer 的作用和使用方法!