在node中,由于应用场景的不同,应用需要处理,网络协议,数据库操作,图片,文件等,在网络和文件操作过程中,还需要处理大量的二进制文件。javascript的字符串远远不能满足这些需求,所以Buffer就应运而生了。
由于Buffer太过常见,Node进程启动时就已经加载了它,所以使用Buffer不需要额外的引入,直接使用就行了。
Buffer内存分配
buffer内存分配不在V8堆内存中,而是在Node的C++层面实现的内存的申请的。因为处理大量的字节数据不能采用需要一点内训就向操作系统申请一点内存的方式,这可能会造成内存申请的系统调用,最操作系统有一定的压力。为此Node在内存的使用上应用的是在C++层面申请的内存,在javascript中分配内存策略。
为了高效的使用申请来的内存,Node采用了slab分配机制。简单而言,slab就是申请好的固定大小的内存区域。它具有三种状态。
- full: 完全分配状态。
- partial: 部分分配状态。
- empty: 没有被分配状态。
当我们需要一个Buffer对象,可以通过以下方式分配指定大小的Buffer对象。
如何创建Buffer
使用Buffer.from(), Buffer.alloc(), Buffer.allocUnsafe()方法可以创建buffer。
const buf = Buffer.from('Hey!')
- Buffer.from(array)
- Buffer.from(arrayBuffer[, byteOffset[, length]])
- Buffer.from(buffer)
- Buffer.from(string[, encodeing])
也可以只初始化buffer(传入大小)
const buf = Buffer.alloc(1024) // 创建一个1kb大小的buffer
// 或
const buf = Buffer.allocUnsafe(1024)
alloc和allocunsafe均分配指定大小的buffer(以字节为单位)。
- alloc创建的buffer会被使用零进行初始化。
- allocunsafe创建的buffer不会被初始化,当内存被读取时,若内存中存在较旧的数据,则可以被访问或泄露,这就是真正使allocUnsafe不安全的原因,在使用的时候要格外的小心。
使用Buffer
const buf = Buffer.from('Hey!')
console.log(buf[0]) // 72
console.log(buf[1]) // 101
console.log(buf[2]) // 121
console.log(buf[3]) // 33
console.log(buf.toString()) // Hey
// 获取buffer长度
console.log(buf.length) // 4
// 写入buffer内容
const buf = Buffer.alloc(5)
buf.write('hello')
buf[2] = 111
console.log(buf.toString()) // heolo
// 复制
const copyBuf = Buffer.alloc(4)
buf.copy(copyBuf)
console.log(buf.toString()) // heol
// 切片
const buf = Buffer.from('hello')
console.log(buf.slice(0, 2).toString()) // he
// 支持的编码类型判定
Buffer.isEncoding(encoding) // encoding: utf-8 hex utf/8...
// 支持的编码类型返回true 不支持返回 false。国内常用的GBK,GB2312,BIG-5不在支持行列中
// 对于不支持的编码类型,可以借助Node生态圈中的模块完成转换。iconv和iconv-lite两个模块可以支持更多的编码类型转换
const iconv = require('iconv-lite')
// buffer转字符串
const str = iconv.decode(buf, 'win1251')
// 字符串转buffer
const newBuf = iconv.encode('wertyu', 'win1251')