在ECMAScript 2015(ES6)引入TypedArray之前,JavaScript语言本身没有读取或者操纵二进制数据流的机制。Buffer类作为Node.js API的一部分引入,使得能够与TCP流或者文件系统操作等字节流交互。
既然ES6中已经加入了TypedArray,Buffer类以更优化与适用Node.js适用场合的方式实现Unit8Array API。Buffer类的实例类似于整型数组,但是对应于V8堆外固定大小原始内存分配。当Buffer创建时,确定其大小,并不能重新改变大小。
在Node.js内部,Buffer类是一个全局量,因此,不太可能需要这样使用
require('buffer').Buffer
例子:
// 创建长度为10的自动填充零值Buffer
const buf1 = Buffer.alloc(10);
// 创建长度为10的Buffer,填充值1
const buf2 = Buffer.alloc(10, 1);
// 创建长度为10的未初始化buffer
// 比调用Buffer.alloc()速度更快,但是返回Buffer实例可能会包含旧数据,
// 需要通过fill()或者write()方法重写
const buf3 = Buffer.allocUnsafe(10);
// 创建包含[0x1, 0x2, 0x3] buffer
const buf4 = Buffer.from([1, 2, 3]);
// 创建包含UTF-8字节 [0x74, 0xc3, 0xa9, 0x73, 0x74] buffer
const buf5 = Buffer.from('tést');
// 创建包含Latin-1字节[0x74, 0xe9, 0x73, 0x74] buffer
const buf6 = Buffer.from('tést', 'latin1');
Buffer.from()、Buffer.alloc()与 Buffer.allocUnsafe()
Node.js v6版本之前,通过Buffer构造函数创建相应实例,根据所提供的参数,分配返回不同buffer
- 给Buffer()传入一个数值作为第一个参数,(例如:new Buffer(10)),分配一个新的特定大小Buffer对象。在Node.js 8.0.0之前,为这样的Buffer实例所分配的内存并未初始化,可以包含敏感数据。这样的Buffer实例必须随后进行初始化,通过或者 buf.fill(0) 或者通过完全写入Buffer。虽然这种行为意在改进性能,研发经历已经说明,在创建快速但未初始化的buffer与稍慢但是更安全的buffer之间需要更直接的区别。
- 传入字符串、数组或者Buffer作为第一个参数,拷贝对象数据到Buffer中
- 传入ArrayBuffer返回与给定ArrayBuffer共享分配内存的Buffer
根据传入第一个参数值类型,new Buffer()行为方式变化非常大,如果应用程序没能合理校验传给new Buffer()的入参,或者未能合理初始化新分配的Buffer内容,可能会无意识的引入代码安全与稳定性问题。
为使得Buffer实例创建更可靠与少出差错,不同形式的new Buffer()构造函数已经被弃用,可以由其他单独方法Buffer.from()、Buffer.alloc()、Buffer.allocUnsafe()替代。
开发者应该将所有现存new Buffer()构造函数迁移到这些新API之一。
Buffer.from(array) 返回包含所提供字节副本的新Buffer
Buffer.from(arrayBuffer[, byteOffset [, length]]) 返回新Buffer,与给定ArrayBuffer共享分配内存
Buffer.from(buffer) 返回新Buffer,包含给定Buffer内容副本
Buffer.from(string[, encoding]) 返回新Buffer,包含所提供字符串副本
Buffer.alloc(size[, fill[, encoding]]) 返回特定大小已填充Buffer实例,该方法会比 Buffer.allocUnsafe(size)慢得多,但是确保新创建Buffer实例不包含旧的前在敏感数据。
Buffer.allocUnsafe(size) 与Buffer.allocUnsafeSlow(size) 每一个返回特定大小新Buffer,内容必须用或者buf.fill(0)或者完全重写进行初始化。
由 Buffer.allocUnsafe()返回的Buffer实例可能会分配共享内部内存池,如果大小不超过Buffer.poolSize一半,由Buffer.allocUnsafeSlow()返回的实例从不使用共享内部内存池。
Buffer.allocUnsafe()与Buffer.allocUnsafeSlow()不安全原因分析
当调用方法Buffer.allocUnsafe() 和Buffer.allocUnsafeSlow()时,分配内存段并未初始化(并未清理处理)。虽然这种设计使得内存分配极其迅速,但是分配所得内存段可能会包含潜在敏感的旧数据。使用由Buffer.allocUnsafe() 方法创建的Buffer,但是未完全重写内存,在读Buffer内存时会泄露旧数据。
虽然使用Buffer.allocUnsafe() 方法会有明显的性能优势,必须额外小心避免引入应用程序安全隐患。
缓冲区与字符编码
const buf = Buffer.from('hello world', 'ascii');
// 打印输出: 68656c6c6f20776f726c64
console.log(buf.toString('hex'));
// 打印输出: aGVsbG8gd29ybGQ=
console.log(buf.toString('base64'));
当前NodeJS支持的字符编码方式包括: