在 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 的作用和使用方法!

小夜