[node] Node.js 缓冲区Buffer

node Node.js 缓冲区Buffer

  • 什么是Buffer
  • Buffer 与字符编码
  • Buffer 的方法概览
  • Buffer 的实例
    • Buffer 的创建
    • 写入缓冲区
    • 从 Buffer 区读取数据
    • 将 Buffer 转换为 JSON 对象
    • Buffer 的合并
    • Buffer 的比较
    • Buffer 的覆盖
    • Buffer 的截取--slice
    • Buffer 的长度
    • writeUIntLE
    • writeUIntBE

什么是Buffer

JavaScript 语言自身只有字符串数据类型,没有二进制数据类型。

但在处理像TCP流或文件流时,必须使用到二进制数据。因此在 Node.js中,定义了一个 Buffer 类,该类用来创建一个专门存放二进制数据的缓存区。

在 Node.js 中,Buffer 类是随 Node 内核一起发布的核心库。Buffer 库为 Node.js 带来了一种存储原始数据的方法,可以让 Node.js 处理二进制数据,每当需要在 Node.js 中处理I/O操作中移动的数据时,就有可能使用 Buffer 库。原始数据存储在 Buffer 类的实例中。一个 Buffer 类似于一个整数数组,但它对应于 V8 堆内存之外的一块原始内存。

在v6.0之前创建Buffer对象直接使用new Buffer()构造函数来创建对象实例,但是Buffer对内存的权限操作相比很大,可以直接捕获一些敏感信息,所以在v6.0以后,官方文档里面建议使用 Buffer.from() 接口去创建Buffer对象。

Buffer 与字符编码

Buffer 实例一般用于表示编码字符的序列,比如 UTF-8 、 UCS2 、 Base64 、或十六进制编码的数据。 通过使用显式的字符编码,就可以在 Buffer 实例与普通的 JavaScript 字符串之间进行相互转换

ts 复制代码
const buf = Buffer.from("test", "ascii");
console.log(buf.toString("hex"));// 输出 74657374
console.log(buf.toString("base64"));// 输出 dGVzdA==

Node.js 目前支持的字符编码包括:

  • ascii - 仅支持 7 位 ASCII 数据。如果设置去掉高位的话,这种编码是非常快的。
  • utf8 - 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8 。
  • utf16le - 2 或 4 个字节,小字节编码的 Unicode 字符。支持代理对(U+10000 至 U+10FFFF)。
  • ucs2 - utf16le 的别名。
  • base64 - Base64 编码。
  • latin1 - 一种把 Buffer 编码成字节编码的字符串的方式。
  • binary - latin1 的别名。
  • hex - 将每个字节编码为两个十六进制字符。

Buffer 的方法概览

写在前面,下面所有方法中:

  • 以LE结尾的API,指定使用endian (Little-Endian)字节序格式读取或写入
  • 以BE结尾的API,指定使用endian (Bid-Endian)字节序格式读取或写入
方法 描述
new Buffer(size) Buffer.alloc(size)或 Buffer.allocUnsafe(size) 分配新的 size 大小单位为8位字节的 buffer。 注意, size 必须小于 kMaxLength,否则,将会抛出异常 RangeError
new Buffer(buffer) Buffer.from(buffer) 拷贝参数 buffer 的数据到 Buffer 实例
new Buffer(str, encoding) Buffer.from(str, encoding) 分配新的 buffer.str 字符串, encoding 编码方式默认为 'utf8'
buf.length 返回 buf 的 bytes 数。注意这未必是 buf 里面内容的大小。length 是 buffer 对象所分配的内存数,若指定size 它不会随着buf 对象内容的改变而改变,若未指定则会发生变化
buf.toString(encoding\[, start\[, end]]) 根据 encoding (默认 utf8)返回解码过的 string 类型。根据 start (默认 0) ,end (默认 buffer.length)作为取值范围
buf.toJSON() 将 Buffer 实例转换为 JSON 对象。
bufindex 获取或设置指定的字节。返回值代表一个字节,所以返回值的合法范围是十六进制0x00到0xFF 或者十进制0至 255。
buf.equals(otherBuffer) 比较两个缓冲区是否相等,相等返回 true,否则返回 false
buf.compare(otherBuffer) 比较两个 Buffer 对象,返回数字,表示 buf 在 otherBuffer 之前,之后或相同
buf.copy(targetBuffer, targetStart\[, sourceStart\[, sourceEnd]]) 将buf指定区间的内容覆盖targetBuffer指定索引开始的相同长度内容,源和目标可以相同。buf开始位置sourceStart(默认0)和结束位置sourceEnd (默认buf的长度)的区间内容,覆盖targetBuffer从targetStart开始的相同长度的内容
buf.slice(start\[, end]) 截取 Buffer 对象,从 start(默认是 0 ) 到 end (默认是 buffer.length ) 的区间。 负的索引是从 buffer 尾部开始计算的
buf.fill(value, offset, end) 使用指定的 value 来填充这个 buffer。如果没有指定 offset (默认是 0) 并且 end (默认是 buffer.length) ,将会填充整个buffer。
buf.write(str, offset\[, length], encoding) 根据offset 偏移量(默认值是 0)和 encoding 编码方式(默认值是 utf8),将 str 数据写入buffer。 length 是将要写入的字符串的 bytes 大小。 返回 number 类型,表示写入了多少 8 位字节流。如果 buffer 没有足够的空间来放整个 str ,它将只会只写入部分字符串。 length 默认是 buffer.length - offset。 这个方法不会出现写入部分字符。
buf.writeUIntLE(value, offset, byteLength, noAssert) 将 value 写入到 buffer 里, 它由 offset 和 byteLength 决定,最高支持 48 位无符号整数。noAssert(默认 false) 为 true ,不再验证 value 和 offset 的有效性
buf.writeUIntBE(value, offset, byteLength, noAssert) 用法同上。注意:无符号整数
buf.writeIntLE(value, offset, byteLength, noAssert) 用法同上。注意:有符号整数
buf.writeIntBE(value, offset, byteLength, noAssert) 用法同上。注意:有符号整数
buf.readUIntLE(offset, byteLength, noAssert) 根据指定的偏移量,支持读取 48 位以下的无符号数字,指定Endian格式。noAssert (默认 false)为 true 时, 不验证offset是否超过 buffer 的长度
buf.readUIntBE(offset, byteLength, noAssert) 用法同上。注意:无符号整数
buf.readIntLE(offset, byteLength, noAssert) 用法同上。注意:有符号整数
buf.readIntBE(offset, byteLength, noAssert) 用法同上。注意:有符号整数
buf.readUInt8(offset, noAssert) 用法同上。注意:支持读取无符号 8 位整数
buf.readUInt16LE(offset, noAssert) 用法同上。注意:读取一个无符号 16 位整数
buf.readUInt16BE(offset, noAssert) 用法同上。注意:读取一个无符号 16 位整数
buf.readUInt32LE(offset, noAssert) 用法同上。注意:读取一个无符号 32 位整数。
buf.readUInt32BE(offset, noAssert) 用法同上。注意:读取一个无符号 32 位整数。
buf.readInt8(offset, noAssert) 用法同上。注意:读取一个有符号 8 位整数
buf.readInt16LE(offset, noAssert) 用法同上。注意:读取一个 有符号 16 位整数
buf.readInt16BE(offset, noAssert) 用法同上。注意:读取一个 有符号 16 位整数
buf.readInt32LE(offset, noAssert) 用法同上。注意:读取一个有符号 32 位整数。
buf.readInt32BE(offset, noAssert) 用法同上。注意:读取一个有符号 32 位整数。
buf.readFloatLE(offset, noAssert) 用法同上。注意:读取一个 32 位双浮点数。
buf.readFloatBE(offset, noAssert) 用法同上。注意:读取一个 32 位双浮点数。
buf.readDoubleLE(offset, noAssert) 用法同上。注意:读取一个 64 位双精度数。
buf.readDoubleBE(offset, noAssert) 用法同上。注意:读取一个 64 位双精度数。
buf.writeUInt8(value, offset, noAssert) 根据 offset 偏移量和 endian格式将 value 写入 buffer。注意:value 必须是一个合法的无符号 8 位整数。 若noAssert 为 true (默认 false)将不会验证 value 和 offset , 这意味着 value 可能过大,或者 offset 可能会超出buffer的末尾从而造成 value 被丢弃。 除非你对这个参数非常有把握,否则尽量不要使用
buf.writeUInt16LE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的无符号 16 位整数
buf.writeUInt16BE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的无符号 16 位整数。
buf.writeUInt32LE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的无符号 32 位整数。
buf.writeUInt32BE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的有符号 32 位整数。
buf.writeInt8(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的 signed 8 位整数。
buf.writeInt16LE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的 signed 16 位整数。
buf.writeInt16BE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的 signed 16 位整数。
buf.writeInt32LE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的 signed 32 位整数。
buf.writeInt32BE(value, offset, noAssert) 用法同上。注意:value 必须是一个合法的 signed 32 位整数。
buf.writeFloatLE(value, offset, noAssert) 用法同上。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的。
buf.writeFloatBE(value, offset, noAssert) 用法同上。注意:当 value 不是一个 32 位浮点数类型的值时,结果将是不确定的
buf.writeDoubleLE(value, offset, noAssert) 用法同上。注意:value 必须是一个有效的 64 位double 类型的值
buf.writeDoubleBE(value, offset, noAssert) 用法同上。注意:value 必须是一个有效的 64 位double 类型的值

Buffer 的实例

Buffer 的创建

  • Buffer.alloc(size, fill\[, encoding]): 返回一个size大小的 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 实例
ts 复制代码
// 创建一个长度为 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('test');

// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf6 = Buffer.from('test', 'latin1');

写入缓冲区

ts 复制代码
buf.write(string[, offset[, length]][, encoding])

根据 encoding 的字符编码写入 string 到 buf 中的 offset 位置。 length 参数是写入的字节数。 如果 buf 没有足够的空间写入整个字符串,则只会写入 string 的一部分。 只部分解码的字符不会被写入.该方法返回实际写入的大小。如果 buffer 空间不足, 则只会写入部分字符串。

  • string:写入缓冲区的字符串
  • offset:偏移量,缓冲区开始写入的索引值,默认为 0
  • length:写入的字节数,默认 buffer.length
  • encoding:编码方式,默认utf8

返回实际写入的大小!!!如果 buffer 空间不足, 则只会写入部分字符串

ts 复制代码
const buf = Buffer.alloc(256);
const len = buf.write("TestDemo1");
console.log(len); // 输出 9
console.log(buf.length); // 输出 256

请注意,上述实例write函数的返回值len是实际的大小,而buf.length则是缓冲区的大小

从 Buffer 区读取数据

ts 复制代码
buf.toString([encoding[, start[, end]]])

解码缓冲区数据并使用指定的编码返回字符串

  • encoding:编码方式,默认utf8
  • start:指定开始读取的索引位置,默认为 0
  • end: 结束位置,默认为缓冲区的末尾
ts 复制代码
const buf = Buffer.alloc(256);
const len = buf.write("TestDemo1");
console.log(len); // 输出 9
console.log(buf.length); // 输出 256
const buf1 = Buffer.alloc(3);
buf1.write("TestDemo1");
console.log(buf1.toString()); // 输出 Tes

将 Buffer 转换为 JSON 对象

ts 复制代码
buf.toJSON()

将 Node Buffer 转换为 JSON 对象,返回 JSON 对象。

ts 复制代码
const buf = Buffer.alloc(3);
const len = buf.write("3");;
console.log(buf.toJSON()); // 输出 { type: 'Buffer', data: [ 51, 0, 0 ] }

Buffer 的合并

ts 复制代码
Buffer.concat(list[, totalLength])

Node 缓冲区合并,返回一个多个成员合并的新 Buffer 对象。

  • list : 用于合并的 Buffer 对象数组列表
  • totalLength : 指定合并后Buffer对象的总长度
ts 复制代码
var buffer1 = Buffer.from("demo1");
var buffer2 = Buffer.from("test2");
var buffer3 = Buffer.concat([buffer1, buffer2]);
var buffer4 = Buffer.concat([buffer1, buffer2],4);
console.log(buffer3.toString()); //demo1test2
console.log(buffer4.toString()); //demo

Buffer 的比较

ts 复制代码
buf.compare(otherBuffer);

Node Buffer 比较,返回一个数字,表示 buf 若与 otherBuffer 第一个字符相匹配返回-1;若是完全匹配返回0;其它从中间开始匹配,或者匹配不上返回1

这个方法是按位比较的

  • otherBuffer: 与 buf 对象比较的另外一个 Buffer 对象
ts 复制代码
var buffer2 = Buffer.from("ABCD");

var buffer1 = Buffer.from("AB");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 -1

var buffer1 = Buffer.from("B");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("E");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("AE");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 1

var buffer1 = Buffer.from("ABCD");
var result = buffer1.compare(buffer2);
console.log(result); // 输出 0

Buffer 的覆盖

ts 复制代码
buf.copy(targetBuffer[, targetStart[, sourceStart[, sourceEnd]]])

截取缓冲区 buf指定长度的内容复制到targetBuffer的指定位置,没有返回值

  • targetBuffer:要被覆盖的 Buffer 对象
  • targetStart:覆盖 Buffer 对象指定开始覆盖的索引位置,默认为 0
  • sourceStart: 用于覆盖的Buffer对象的指定开始位置,默认为 0
  • sourceEnd: 用于覆盖的Buffer对象的指定结束位置,默认: buffer.length
ts 复制代码
var buf1 = Buffer.from("abcdefghijkl");
var buf2 = Buffer.from("RUNOOB");

//将 buf2 插入到 buf1 指定位置上
buf2.copy(buf1, 2, 0, 2);

console.log(buf1.toString());//abRUefghijkl
console.log(buf2.toString());//RUNOOB

Buffer 的截取--slice

ts 复制代码
buf.slice([start[, end]])

返回指定区间内的缓冲区,它和旧缓冲区指向同一块内存,从索引 start 到 end 的位置区间.被截取缓冲区不变

  • start:数字, 可选, 默认 0
  • end: 数字, 可选, 默认 buffer.length
ts 复制代码
var buffer1 = Buffer.from("Test");
// 剪切缓冲区
var buffer2 = buffer1.slice(0, 2);
var buffer3 = Buffer.from("M");
buffer3.copy(buffer1);
console.log(buffer2.toString());//Me
console.log(buffer1.toString());//Mest

Buffer 的长度

ts 复制代码
const buf = Buffer.from("Test");
console.log(buf.length); // 输出 4
const buf1 = Buffer.from("TestDemo1");
console.log(buf1.length); // 输出 9

writeUIntLE

ts 复制代码
const buf = Buffer.allocUnsafe(6);
buf.writeUIntLE(0x1234567890ab, 0, 6);
// 输出: <Buffer ab 90 78 56 34 12>
console.log(buf);

writeUIntBE

ts 复制代码
const buf = Buffer.allocUnsafe(6);
buf.writeUIntBE(0x1234567890ab, 0, 6);
// 输出: <Buffer 12 34 56 78 90 ab>
console.log(buf);
相关推荐
Patrick_Wilson7 分钟前
K8s 探针避坑:Next.js 不同部署模式下的健康检查实践
kubernetes·node.js·next.js
我登哥MVP4 小时前
VS Code 安装 Claude Code 并接入 DeepSeek V4 Model
人工智能·python·node.js·agent·codex·deepseek·claude code
Patrick_Wilson5 小时前
Node.js SSR 内存治理:为什么 --max-old-space-size 不等于进程内存
kubernetes·node.js·v8
fred_kang7 小时前
Claude Code 在 Windows 切换 Node.js 版本后命令失效的排查与解决
node.js
xiaofeichaichai16 小时前
Webpack
前端·webpack·node.js
Python私教19 小时前
把开源 Agent 打包成"解压双击即用"的 Windows 便携包:一条命令的完整实现
node.js
没事别瞎琢磨21 小时前
十一、审计与 Run Session——每一步操作都被记录
人工智能·node.js
没事别瞎琢磨21 小时前
十六、AgentSandbox——把所有模块串起来的编排类
人工智能·node.js
没事别瞎琢磨21 小时前
十二、网络代理与白名单规则引擎
人工智能·node.js
没事别瞎琢磨21 小时前
十四、Git Worktree 隔离执行
人工智能·node.js