笔者在最近的一两个月的开发中,一直在频繁的使用 Buffer,故将工作中常使用方式总结出来,以供大家参考和查阅,也可作为自己的备忘录。
创建
Buffer.alloc: 当已知 buffer 的长度的时候可以使用 Buffer.alloc 进行创建,其接收三个参数:
- length,buffer 的长度
- fill, 默认填充值
- encoding, 如果 fill 是个字符串,可以指定字符串的编码
let buf = Buffer.alloc(3);
Buffer.allocUnsafe: 内存内容未初始化,可能包含敏感信息,需要使用 Buffer.fill 进行初始化
let buf = Buffer.allocUnsafe(3);
buf.fill(0)
Buffer.from: 当需要根据内容创建 buffer 的时候使用该函数,参数可以为 字符串
、buffer 数据
、 整数数组
,具体如下:
let buf = Buffer.from("abc");
console.log(buf);
let buf2 = Buffer.from([0x61, 0x62, 0x63]);
console.log(buf2);
let buf3 = Buffer.from(buf);
console.log(buf3);
注意在给 from 传参数的时候一定要确实是以上类型,不然可以会抛出异常:
First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object
写入
笔者在工作中较常写入的是数字,就以整数为例,其他类似,比如需要写入数据的 T(type)、L(length)
buf.writeInt8: 给 buffer 中写入整数数据,包含两个参数:value(写入的值) 和 offset(写入的起点)
buf.writeInt8(101, 0);
writeInt16BE: 写入大端 2 个字节数据,大端表示高位在前, 相对的 writeInt16LE 表示地位在前
let buf = Buffer.alloc(3);
buf.writeInt8(101, 0);
buf.writeInt16BE(200, 1);
console.log(buf);
// <Buffer 65 00 c8> 其中展示的数据均为 16 进制
注意指定的写入起点一定在 buffer 的长度范围之内,不然会出现RangeError: Index out of range
, 如改写上面例子
buf.writeInt16BE(200, 2);
//RangeError: Index out of range
// at checkInt (buffer.js:1178:11)
// at Buffer.writeInt16BE (buffer.js:1355:5)
//
读取
Buffer.readInt8: 指定 buffer 开始读取位置,然后读取一位
let buf = Buffer.alloc(3);
buf.writeInt8(101, 0);
buf.writeInt16BE(200, 1);
console.log(buf.readInt8(0)); // 101
Buffer.readInt16BE: 与写入相对,读取也分为大小端,按照大端方式读取数据,并且读取两位
let buf = Buffer.alloc(3);
buf.writeInt8(101, 0);
buf.writeInt16BE(200, 1);
console.log(buf.readInt16BE(1)); // 200
拼接
Buffer.concat: 对于已有 buffer 数据进行拼接, 接收一个 buffer list 如:[buffer1, buffer2…]和拼接生成的 buffer 总长度,可不指定, 如一下拼接一个 TLV 数据,格式如下:
let buf = Buffer.alloc(3);
const length = 200;
const type = 101;
const value = Buffer.from("abc");
buf.writeInt8(type, 0); //type
buf.writeInt16BE(length, 1);
const result = Buffer.concat([buf, value]);
console.log(result); // <Buffer 65 00 c8 61 62 63>
转换
buffer.toString: 支持一下几种方式转换:
- hex, 将二进制内容转为 16 进制
- base64, 转为 base64 编码 // 数据传输中常用
- ascii, ascii 编码
- utf8,UTF- 8 编码
//result 为前面例子的结果
result.toString('base64'); // ZQDIYWJj
const buf1 = Buffer.allocUnsafe(26);
for (let i = 0; i < 26; i++) {
// 97 is the decimal ASCII value for 'a'.
buf1[i] = i + 97;
}
console.log(buf1.toString('ascii'));
笔者比较常用的是将 TLV 数据转为 base64 编码,具体原理可以查看 Base64 编码与解码详解