深入理解Nodejs中的Buffer类
Opened this issue · 0 comments
前言
描述Buffer之前,先需要了解js的一些比较底层的原生知识
- ArrayBuffer
- Int8Array
- TypedArray
ArrayBuffer
ArrayBuffer 对象来表示通用的,固定长度的原始二进制数据缓冲区。
简单说,ArrayBuffer就是一块内存,不方便直接用它,就像C语言 malloc申请一块内存,也会把它转换为实际上所需要的数组/指针来使用
它只是一堆01串,并不知道字节有多长,该用多少位去存
new ArrayBuffer(length): length代表申请ArrayBuffer的大小,单位为字节
Int8Array
我们可以通过Int8类型的数组,告诉ArrayBuffer,你需要将01串分割成以8位为一组的序列
var buffer = new ArrayBuffer(1024)
var arr = new Int8Array(buffer) // 使用buffer创建一个8位的数组,
// 一个字节=8位,所以数组长度是1024
TypedArray
在js中,你找不到名为TypedArray的构造函数,其实它只是一个名称,是下面几个类型的统称
- Int8Array();
- Uint8Array();
- Uint8ClampedArray();
- Int16Array();
- Uint16Array();
- Int32Array();
- Uint32Array();
- Float32Array();
- Float64Array();
简单说,它的作用就是告诉ArrayBuffer应该以怎样的形式来分离存放二进制字节
Buffer
有了前面的基础后,我们来看看node中的Buffer类
Buffer实例其实也是Uint8Array的实例,但是与TypedBuffer有一些微小的不同
例如:TypedBuffer.slice方法会创建一个新的数组拷贝
而Buffer.slice会在原先的数组上做修改
在Node 6.0之前,Buffer实例是由Buffer构造函数创建的
var buffer = new Buffer(10)
但是这种方式存在两个问题
- 参数复杂,容易出错,传数字或者字符串或者ArrayBuffer会有不同的效应
- 安全隐患,分配到的内存可能还存储着旧数据
具体的安全隐患例子:
第一个参数如果是100,new Buffer("100")
会为字符串"100"分配三个字节的内存本来我的程序中是默认接收字符串来分配内存的,但是攻击者如果恶意的传入很大的数字9999999999999
就会导致
new Buffer(999999999999)
申请了一个超大内存,导致内存耗尽,服务器奔溃
所以新的Buffer提供了四个方法来申请内存
- Buffer.from()
- Buffer.alloc()
- Buffer.allocUnsafe()
- Buffer.allocUnsafeSlow()
Buffer.from()
Buffer.from()是根据已有的数据创建Buffer实例,不接收数字为参数
Buffer.from(obj) // obj支持array, arrayBuffer, buffer,
Buffer.alloc()
Buffer.alloc()是申请内存,
Buffer.alloc(size) // 分配size大小的内存,并填充为0
Buffer.allocUnsafe()和Buffer.allocUnsafeSlow()
这两者和alloc的区别就是
alloc会将字节填充为0,
这两个不会做填充,分配的内存没有初始化,可能是旧内存,所以不安全,也就更快了
使用Buffer
常见的就是对Buffer进行转换,转换为字符串转换为JSON,一般通过toXXX就可以实现了
Buffer的行为更类似于静态语言里的数组,而不像传统的js数组
如slice方法不会创建新数组,而是在原数组上做修改
长度一但确定就不会再发生改变
...
具体增删,读写,清空合并可以查API
更重要的是在流中,使用到了Buffer进行传输