zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Node.js Buffer

JSNode Buffer
2023-09-11 14:22:55 时间

一、Instance

1、Buffer.alloc(length[, value])
声明一个长度为length的字节数组,默认用0填充,否则用value填充。
注意:value的取值范围是8bit无符号数值,不属于此范围的都将会被截取低位,而高位被抛弃。

2、Buffer.allocUnsafe(length)
创建一个长度为length的未初始化的字节数组。它比起alloc快的多,但是它返回的是一个未经处理的空间,可能包含原先该空间中旧数据,需要使用 fill() 或 write() 来覆写。

3、Buffer.from(buffer)
创建一个字节数组的副本。因此后续原Buffer的值发生变化并不会影响到当前数组。

4、Buffer.from(arrayBuffer[, byteOffset [, length]])
将全部由[-255,255]的数字组成的数组,转化为字节数组。
注意:value的取值范围是8bit无符号数值,不属于此范围的都将会被截取低位,而高位被抛弃。另外如果array中包含非数字会报SyntaxError: Unexpected token ILLEGAL。

5、Buffer.from(string[, encoding])
将字符串转化为字节数组,默认的编码方式为utf8。

const buf1 = Buffer.alloc(10);
//返回 <Buffer 00 00 00 00 00 00 00 00 00 00>

const buf2 = Buffer.alloc(10, 1);
//返回 <Buffer 01 01 01 01 01 01 01 01 01 01>

const buf3 = Buffer.allocUnsafe(10);
//返回 不确定

const buf4 = Buffer.from(buf2);
//返回 <Buffer 01 01 01 01 01 01 01 01 01 01>
buf2[0] = 0xff;
console.log(buf2);
//输出 <Buffer ff 01 01 01 01 01 01 01 01 01>
console.log(buf4);
//输出 <Buffer 01 01 01 01 01 01 01 01 01 01>

const buf5 = Buffer.from([1,2,3,255,256,257,-1,-255,-256,-257]);
//返回 <Buffer 01 02 03 ff 00 ff 01 00>

const buf6 = Buffer.from('test');
//返回 <Buffer 74 65 73 74>

const buf7 = Buffer.from('tést');
//返回 <Buffer 74 c3 a9 73 74>

const buf8 = Buffer.from('tést', 'utf8');
//返回 <Buffer 74 c3 a9 73 74>

二、Character Encodings

  1. ‘ascii’ - for 7-bit ASCII data only. This encoding is fast and will strip the high bit if set.
  2. ‘utf8’ - Multibyte encoded Unicode characters. Many web pages and other document formats use utf8.
  3. ‘utf16le’ - 2 or 4 bytes, little-endian encoded Unicode characters. Surrogate pairs (U+10000 to U+10FFFF) are supported.
  4. ‘ucs2’ - Alias of ‘utf16le’.
  5. ‘base64’ - Base64 encoding. When creating a Buffer from a string, this encoding will also correctly accept “URL and Filename Safe Alphabet” as specified in RFC4648, Section 5.
  6. ‘latin1’ - A way of encoding the Buffer into a one-byte encoded string (as defined by the IANA in RFC1345, page 63, to be the Latin-1 supplement block and C0/C1 control codes).
  7. ‘binary’ - Alias for ‘latin1’.
  8. ‘hex’ - Encode each byte as two hexadecimal characters.

ASCII是为英语设计的,但显然这个世界不仅仅使用英语或者英文字符来交流。在最近几年,Web上选择的编码方式是UTF-8。它可以表达Unicode这一包括了当今世界上的大多数语言和字符集合中的每个字符。UTF-8使用1到4个字节用来表达字符并且完全向后兼容ASCII。对于被认为是会经常使用的字符就使用少一些的字节数(通常是一个)来编码,而不常用的字符则使用4个字节来编码。

4个比特或半个字节称为Nibble。由于一个Nibble是4比特,所以它可以有16个可能的值。这也可以称为十六进制(hexadecimal或简称hex)或者以16为基数,就是因为它有16个可能的值。

const buf = Buffer.from('hello world', 'ascii');
console.log(buf);
//输出 <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>

console.log(buf.toString('hex'));
//输出 68656c6c6f20776f726c64

console.log(buf.toString('base64'));
//输出 aGVsbG8gd29ybGQ=

三、TypedArray

Buffer.from(array),默认只会取低8比特进行赋值,并生成副本;,如果要保留array的所有值,需要用array.buffer,然后调用Buffer.from(buffer)构造Buffer视图(注意:这里生成的是视图,不是副本)

var arr = new Uint16Array(2);
arr[0] = 4000;
arr[1] = 5000;
const buf1 = Buffer.from(arr);
const buf2 = Buffer.from(arr.buffer);
console.log(buf1);
//输出 <Buffer a0, 88>,注意:这里只截取了低位,高位自动省略
console.log(buf2);
//输出 <Buffer a0 0f 88 13>,注意:这里是小尾存储4000=0x0fa0

arr[1] = 6000;
console.log(buf1);
//输出 <Buffer a0, 88>
console.log(buf2);
//输出 <Buffer a0 0f 70 17>,修改原数组中已有的元素buffer会随之改变

arr[2] = 7000;
console.log(buf1);
//输出 <Buffer a0, 88>
console.log(buf2);
//输出 <Buffer a0 0f 70 17>, 新增原数组buffer长度不会改变

Buffer 等价于 Uint8Array。然而在ECMAScript 2015的TypedArray说明中也有一些微妙的不兼容。举个例子,ArrayBuffer.slice([start[, end]]) 创建一个切片副本,而Buffer.slice([start[, end]]) 创建则是通过在当前Buffer上创建一个视图,并没有生成一个副本,因此Buffer.slice([start[, end]])效率更高。

const arr3 = [1, 2, 3];
const arr4 = arr3.slice(1,2);
arr4[0] = 0;
console.log(arr3);
//输出 [ 1, 2, 3 ],说明array.slice生成的是一个副本

const buf3 = Buffer.from(arr3);
const buf4 = buf3.slice(1,2);
buf4[0] = 0;
console.log(buf3);
//输出 <Buffer 01 00 03>,说明buffer.slice生成的是一个视图

四、Buffer.concat(list[, totalLength])

var buf1 = Buffer.alloc(1);
var buf2 = Buffer.alloc(2, 2);
var buf3 = Buffer.from([3,4,5]);

var buf4 = [buf1, buf2, buf3];
//返回 [ <Buffer 00>, <Buffer 02 02>,<Buffer 03 04 05> ]

var buf5 = Buffer.concat(buf4, 6);
//返回 <Buffer 00 02 02 03 04 05>

var buf6 = Buffer.concat(buf4, 3);
//返回 <Buffer 00 02 02>

五、Buffer.compare(buf1, buf2)

buffer内存储的是无符号8比特数值。因此比较的时候是按无符号进行比较的。比较方式:按长度较小的buffer,逐位比较,一旦分出大小则返回,如果比较完还未分出大小,那么规定长度大的buffer大。

var buf1 = Buffer.from([3,1]);
var buf2 = Buffer.from([1,2,3]);
var buf3 = Buffer.from([3,1,0]);
var buf4 = Buffer.from([-3,1]);
Buffer.compare(buf1, buf2);
//输出 1
buf2.compare(buf1);
//输出 -1
buf1.compare(buf3);
//输出 -1
buf1.compare(buf4);
//输出 -1

六、buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])

const buf1 = Buffer.from([1,2,3,4,5]);
const buf2 = Buffer.alloc(3);
buf1.copy(buf2, 0, 1, 2);
console.log(buf2);
//输出 <Buffer 02 00 00>

七、Iterator

通过console.log打印出来的buffer都是16进制形式的。而通过Buffer.entries()、Buffer.keys()、Buffer.values()获取到的都是10进制形式的。

(1)buf.entries()
使用迭代器Iterator遍历Buffer获取 [索引, 值] 对。

const buf = Buffer.from('buffer');
//返回 <Buffer 62 75 66 66 65 72>
for(var pair of buf.entries()) {
    console.log(pair);
}
/*
输出
[ 0, 98 ]
[ 1, 117 ]
[ 2, 102 ]
[ 3, 102 ]
[ 4, 101 ]
[ 5, 114 ]
*/

(2)buf.keys()
获取Buffer索引编号迭代器。

const buf = Buffer.from('buffer');
//返回 <Buffer 62 75 66 66 65 72>
for(var key of buf.keys()) {
    console.log(key);
}
/*
输出
0
1
2
3
4
5
*/

(3)buf.values()
获取Buffer值迭代器。

const buf = Buffer.from('buffer');
//返回 <Buffer 62 75 66 66 65 72>
for(var value of buf.values()) {
    console.log(value);
}
/*
输出
98
117
102
102
101
114
*/

八、indexOf

(1)buf.indexOf(value[, byteOffset][, encoding])
(2)buf.lastIndexOf(value[, byteOffset][, encoding])
(3)buf.includes(value[, byteOffset][, encoding])

var buf = Buffer.from('buf has a child buffer');
buf.indexOf('buf');
//输出 0

buf.indexOf('buf', 1, 'utf8');
//输出 16

buf.indexOf('buf', 1, 'base64');
//输出 -1

buf.lastIndexOf('buf');
//输出 16

buf.includes('buf');
//输出 true

九、read……BE、read……LE

BE 表示 big endian,大尾(大端)编码,即数据的高字节存放在低地址位。
LE 表示 little endian,小尾(小端)编码,即数据的高字节存放在高地址位。

被省略部分可以是如下字符

  1. Double
  2. Float
  3. Int8
  4. Int16
  5. Int32
  6. Int
  7. UInt8
  8. UInt16
  9. UInt32
  10. UInt

readInt、readUInt的格式为

buf.readIntBE(offset, byteLength[, noAssert])

其它显示指明长度或是隐式指明长度的格式为

buf.readDoubleBE(offset[, noAssert])

参数说明

offset Where to start reading. Must satisfy: 0 <= offset <= buf.length - 1
noAssert Skip offset validation? Default: false

var buf = Buffer.from([1,2,3,4,5]);
buf.readUIntBE(0, 2);
//输出 258,<=> 0x0102,大尾编码
buf.readUIntLE(0, 2);
//输出 513,<=> 0x0201,小尾编码

十、write……BE、write……LE

将value写入Buffer,同步方法,返回已写入的长度。

  1. buf.write(string[, offset[, length]][, encoding])
  2. buf.writeDoubleBE(value, offset[, noAssert])
  3. buf.writeDoubleLE(value, offset[, noAssert])
  4. buf.writeFloatBE(value, offset[, noAssert])
  5. buf.writeFloatLE(value, offset[, noAssert])
  6. buf.writeInt8(value, offset[, noAssert])
  7. buf.writeInt16BE(value, offset[, noAssert])
  8. buf.writeInt16LE(value, offset[, noAssert])
  9. buf.writeInt32BE(value, offset[, noAssert])
  10. buf.writeInt32LE(value, offset[, noAssert])
  11. buf.writeIntBE(value, offset, byteLength[, noAssert])
  12. buf.writeIntLE(value, offset, byteLength[, noAssert])
  13. buf.writeUInt8(value, offset[, noAssert])
  14. buf.writeUInt16BE(value, offset[, noAssert])
  15. buf.writeUInt16LE(value, offset[, noAssert])
  16. buf.writeUInt32BE(value, offset[, noAssert])
  17. buf.writeUInt32LE(value, offset[, noAssert])
  18. buf.writeUIntBE(value, offset, byteLength[, noAssert])
  19. buf.writeUIntLE(value, offset, byteLength[, noAssert])

参数说明

value Number to be written to buf
offset Where to start writing. Must satisfy: 0 <= > offset <= buf.length - 4
noAssert Skip value and offset validation? Default: false
Return: offset plus the number of bytes written

var buf = Buffer.allocUnsafe(2);
buf.write('buffer');
//返回 2,为写入数据的长度
buf.write('buffer',0,1,'utf8');
//返回 1

十一、swap

Interprets buf as an array of unsigned 16(32或64)-bit integers and swaps the byte-order in-place. Throws a RangeError if buf.length is not a multiple of 2(4或8).

将 buf 解释为一个无符号 16(32或64)位的整形数组,并且就地交换字节序列。如果 buf 的长度不是 2(4或8)的整数倍,则会抛出一个RangeError异常。

  1. buf.swap16()
  2. buf.swap32()
  3. buf.swap64()
var buf = Buffer.from([1,2,3,4,5,6,7,8]);
buf.swap16();
//输出 <Buffer 02 01 04 03 06 05 08 07>

var buf = Buffer.from([1,2,3,4,5,6,7,8]);
buf.swap32();
//输出 <Buffer 04 03 02 01 08 07 06 05>

var buf = Buffer.from([1,2,3,4,5,6,7,8]);
buf.swap64();
//输出 <Buffer 08 07 06 05 04 03 02 01>