Buffer对象

在 ECMAScript 2015 (ES6) 引入 TypedArray 之前,JavaScript 语言没有读取或操作二进制数据流的机制。 Buffer 类被引入作为 Node.js API 的一部分,使其可以在 TCP 流或文件系统操作等场景中处理二进制数据流。
Buffer 类在 Node.js 中是一个全局变量,因此无需使用 require(‘buffer’)。

创建一个Buffer对象

Buffer对象类似于数组,它的元素为16进制的两位数,即0到255的数值。

  • Buffer.from(array) 返回一个新建的包含所提供的字节数组的副本的 Buffer。
  • Buffer.from(arrayBuffer[, byteOffset [, length]]) 返回一个新建的与给定的 ArrayBuffer 共享同一内存的 Buffer。
  • 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) 返回一个新建的指定 size 的 Buffer,但它的内容必须被初始化,可以使用 buf.fill(0) 或完全写满。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    // 创建一个长度为 10、且用 0 填充的 Buffer。
    const buf1 = Buffer.alloc(10);

    // 创建一个长度为 10、且用 0x1 填充的 Buffer。
    const buf2 = Buffer.alloc(10, 1);

    // 创建一个长度为 10、且未初始化的 Buffer。
    // 这个方法比调用 Buffer.alloc() 更快,

    // 但返回的 Buffer 实例可能包含旧数据,
    // 因此需要使用 fill() 或 write() 重写。
    const buf3 = Buffer.allocUnsafe(10);
    buf3.fill(0)

    // 创建一个包含 [0x1, 0x2, 0x3] 的 Buffer。数组里一定是0-255的数,否则会不识别,返回00
    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');

在 Node.js v6 之前的版本中Buffer 实例是通过 new Buffer 构造函数创建的,因为 new Buffer() 的行为会根据所传入的第一个参数的值的数据类型而明显地改变,所以如果应用程序没有正确地校验传给 new Buffer() 的参数、或未能正确地初始化新分配的 Buffer 的内容,就有可能在无意中为他们的代码引入安全性与可靠性问题。
为了使 Buffer 实例的创建更可靠、更不容易出错,各种 new Buffer() 构造函数已被 废弃,并由 Buffer.from()、Buffer.alloc()、和 Buffer.allocUnsafe() 方法替代。

Node.js 建议开发者们应当把所有正在使用的 new Buffer() 构造函数迁移到这些新的 API 上。

Buffer 的转换

Buffer对象与普通的 JavaScript 字符串的互相转换,需要指定编码格式。目前Node.js 目前支持以下的字符编码。

  • ‘ascii’ - 仅支持 7 位 ASCII 数据。
  • ‘utf8’
  • ‘utf16le’
  • ‘ucs2’
  • ‘base64’
  • ‘latin1’
  • ‘binary’
  • ‘hex’
1
2
3
4
5
6
7
8
// 字符串转Buffer
const buf = Buffer.from('node', 'ascii');

// Buffer转hex编码字符串 - 输出 6e6f6465
console.log(buf.toString('hex'));

// Buffer转base64编码字符串 - 输出 bm9kZQ==
console.log(buf.toString('base64'));

字符串转Buffer

Buffer.from(string[, encoding])
encoding 不传参数会默认utf8编码进行转码和存储。

字符串转Buffer

实例方法
buf.toString([encoding[, start[, end]]])
encoding 解码使用的字符编码。默认: ‘utf8’。
start 开始解码的字节偏移量。默认: 0。
end 结束解码的字节偏移量(不包含)。 默认: buf.length。
注:如果Buffer对象由多种编码写入,就需要在局部指定定不同的编码,才能转换回正常的编码。

判断一个对象是否是Buffer对象

Buffer.isBuffer(obj)
如果 obj 是一个 Buffer 则返回 true ,否则返回 false 。

1
2
const buf1 = Buffer.alloc(10);
console.log(Buffer.isBuffer(buf1)) # 返回true

合并Buffer

Buffer.concat(list[, totalLength])
list <Array> 要合并的 Buffer 或 Uint8Array 实例的数组
totalLength <integer> 合并时 list 中 Buffer 实例的总长度
返回一个合并了 list 中所有 Buffer 实例的新建的 Buffer 。
如果 list 中没有元素、或 totalLength 为 0 ,则返回一个新建的长度为 0 的 Buffer 。
如果没有提供 totalLength ,则从 list 中的 Buffer 实例计算得到。 为了计算 totalLength 会导致需要执行额外的循环,所以提供明确的长度会运行更快。
如果提供了 totalLength,totalLength 必须是一个正整数。如果从 list 中计算得到的 Buffer 长度超过了 totalLength,则合并的结果将会被截断为 totalLength 的长度。

1
2
3
4
5
6
7
8
const buf1 = Buffer.from('蓝');
const buf2 = Buffer.from('胖');
const buf3 = Buffer.from('纸');

const len = buf1.length + buf2.length + buf3.length;
console.log(len) # 输出9 一个汉字三个字节

console.log(Buffer.concat([buf1, buf2, buf3], len).toString())

获取字符长度

Buffer.byteLength(string[, encoding])
encoding 不传参数会默认utf8编码

1
console.log(Buffer.byteLength('蓝胖')) # 输出6 一个汉字三个字节

参考

http://nodejs.cn/api/buffer.html