本质
关于Node中的buffer模块,官方描述是缓冲区。其实你如果去看他的源码的话会发现,buffer就是一个Uint8Array的子类。得到这个结论的话,通俗的来讲buffer就是为了方便我们去操作ArrayBuffer的一个公共类库,跟类型化数组一个概念,只不过比类型化数组更方便。官方文档传送门点击这里。
二进制数据在内存中的存储和读取。
1、存储
我们学习buffer之前,我们需要先搞懂一个问题:
二进制数据在内存中是如何存储的?(在这里我们用一行代码一张图的方式来学习。话不多说,直接上代码!!!)
-
例子
const ab = new ArrayBuffer(2)上面代码表述的是:我们向内存申请2个字节的空间,一个字节等于8位,所以总共16位。如下图(一个方格表示一位):
继续往下走...
//接上面代码 const ua = new Uint8Array(ab); ua[0] = 10; ua[1] = 25;因为
ArrayBuffer是只读的,所以我们必须使用类型化数组或者DataView来操作ArrayBuffer。在上述代码中:我们给ArrayBuffer中第一个字节存储10(对应二进制1010)、第二个字节存储25(对应二进制11001),并且是由低位到高位存储,空位用0填充,最后得到的结果如下图所示:
2、读取
接下来就是我们的主角buffer登场!!!
//接上面代码
const ab = new ArrayBuffer(2)
const ua = new Uint8Array(ab);
ua[0] = 10;
ua[1] = 25;
const buf = Buffer.from(ua);
buf.readInt8(1)//25
这个例子就是读取第二个字节存储的数据,结果返回25。那么接下来再看另外俩个api:
2.1、buf.readUint16BE(按照16位无符号整数进行读取----大端序)
我们先看一下用buf.readUint16BE去读结果是什么?结果如下:
//接上面代码
buf.readInt16BE(0)//2585
返回的结果是2585,接下来看一下它的读取过程。如下图:
小提示:2585的二进制是101000011001
2.2、buf.readUint16LE(按照16位无符号整数进行读取----小端序)
老规矩,我们先看一下用buf.readUint16E去读结果是什么?结果如下:
//接上面代码
buf.readInt16LE(0)//6410
返回的结果是6410,接下来看一下它的读取过程。如下图:
小提示:6410的二进制是 1100100001010
2.3、BE与LE对比
总结一下:就读取顺序来说其实BE更符合人类的阅读习惯(从左往右)、LE更符合计算机的阅读习惯(从右往左)
拓展
- new Uint8Array() 单位是1个字节,也就是8位(存储0~255)
- new Uint16Array() 单位是2个字节,也就是16位(存储0~65535)
- new Uint32Array() 单位是4个字节,也就是32位(存储0~4294967295)
- new Uint64Array() 单位是4个字节,也就是32位(存储0~18446744073709551615)
- new Int8Array() 单位是1个字节,也就是8位(存储-128 ~ 127)
- new Int16Array() 单位是2个字节,也就是16位(存储-32768 ~ 32767)
- new Int32Array() 单位是4个字节,也就是32位(存储-2147483648 ~ 2147483647)
- new Int64Array() 单位是4个字节,也就是32位(存储-9223372036854775808 ~ 9223372036854775807)