Node.js v14.14.0 文档


目录

Buffer(缓冲器)#

中英对照

稳定性: 2 - 稳定

源代码: lib/buffer.js

Buffer 对象用于表示固定长度的字节序列。 许多 Node.js API 都支持 Buffer

Buffer 类是 JavaScript 的 Uint8Array 类的子类,且继承时带上了涵盖额外用例的方法。 只要支持 Buffer 的地方,Node.js API 都可以接受普通的 Uint8Array

Buffer 类在全局作用域中,因此无需使用 require('buffer').Buffer

// 创建一个长度为 10 的 Buffer,
// 其中填充了全部值为 `1` 的字节。
const buf1 = Buffer.alloc(10);

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

// 创建一个长度为 10、且未初始化的 Buffer。
// 这个方法比调用 Buffer.alloc() 更快,
// 但返回的 Buffer 实例可能包含旧数据,
// 因此需要使用 fill()、write() 或其他能填充 Buffer 的内容的函数进行重写。
const buf3 = Buffer.allocUnsafe(10);

// 创建一个包含字节 [1, 2, 3] 的 Buffer。
const buf4 = Buffer.from([1, 2, 3]);

// 创建一个包含字节 [1, 1, 1, 1] 的 Buffer,
// 其中所有条目均使用 `(value & 255)` 进行截断以符合 0-255 的范围。
const buf5 = Buffer.from([257, 257.5, -255, '1']);

// 创建一个 Buffer,其中包含字符串 'tést' 的 UTF-8 编码字节:
// [0x74, 0xc3, 0xa9, 0x73, 0x74](以十六进制表示)
// [116, 195, 169, 115, 116](以十进制表示)
const buf6 = Buffer.from('tést');

// 创建一个包含 Latin-1 字节 [0x74, 0xe9, 0x73, 0x74] 的 Buffer。
const buf7 = Buffer.from('tést', 'latin1');

Buffer 与字符编码#

中英对照

当在 Buffer 和字符串之间转换时,可以指定字符编码。 如果未指定字符编码,则使用 UTF-8 作为默认值。

const buf = Buffer.from('hello world', 'utf8');

console.log(buf.toString('hex'));
// 打印: 68656c6c6f20776f726c64
console.log(buf.toString('base64'));
// 打印: aGVsbG8gd29ybGQ=

console.log(Buffer.from('fhqwhgads', 'utf8'));
// 打印: <Buffer 66 68 71 77 68 67 61 64 73>
console.log(Buffer.from('fhqwhgads', 'utf16le'));
// 打印: <Buffer 66 00 68 00 71 00 77 00 68 00 67 00 61 00 64 00 73 00>

Node.js 当前支持的字符编码如下:

  • 'utf8': 多字节编码的 Unicode 字符。 许多网页和其他文档格式都使用 UTF-8。 这是默认的字符编码。 当将 Buffer 解码为不专门包含有效 UTF-8 数据的字符串时,则会使用 Unicode 替换字符 U+FFFD � 来表示这些错误。

  • 'utf16le': 多字节编码的 Unicode 字符。 与 'utf8' 不同,字符串中的每个字符都会使用 2 个或 4 个字节进行编码。 Node.js 仅支持 UTF-16小端序变体。

  • 'latin1': Latin-1 代表 ISO-8859-1。 此字符编码仅支持从 U+0000U+00FF 的 Unicode 字符。 每个字符使用单个字节进行编码。 超出该范围的字符会被截断,并映射成该范围内的字符。

使用以上方法之一将 Buffer 转换为字符串,称为解码;将字符串转换为 Buffer,称为编码。

Node.js 还支持以下两种二进制转文本的编码。 对于二进制转文本的编码,其命名约定是相反的:将 Buffer 转换为字符串通常称为编码,而将字符串转换为 Buffer 则称为解码。

  • 'base64': Base64 编码。 当从字符串创建 Buffer 时,此编码也会正确地接受 RFC 4648 第 5 节中指定的 “URL 和文件名安全字母”。 base64 编码的字符串中包含的空格字符(例如空格、制表符和换行)会被忽略。

  • 'hex': 将每个字节编码成两个十六进制的字符。 当解码仅包含有效的十六进制字符的字符串时,可能会发生数据截断。 请参见下面的示例。

还支持以下传统的字符编码:

  • 'ascii': 仅适用于 7 位 ASCII 数据。 当将字符串编码为 Buffer 时,这等效于使用 'latin1'。 当将 Buffer 解码为字符串时,则使用此编码会在解码为 'latin1' 之前额外取消设置每个字节的最高位。 通常,当在编码或解码纯 ASCII 文本时,应该没有理由使用这种编码,因为 'utf8'(或者,如果已知的数据始终为纯 ASCII,则为 'latin1')会是更好的选择。 这仅为传统的兼容性而提供。

  • 'binary': 'latin1' 的别名。 有关此编码的更多背景,请参阅二进制字符串。 该编码的名称可能会引起误解,因为此处列出的所有编码都是在字符串和二进制数据之间转换。 对于在字符串和 Buffer 之间进行转换,通常 'utf-8' 是正确的选择。

  • 'ucs2': 'utf16le' 的别名。 UCS-2 以前是指 UTF-16 的一种变体,该变体不支持代码点大于 U+FFFF 的字符。 在 Node.js 中,始终支持这些代码点。

Buffer.from('1ag', 'hex');
// 打印 <Buffer 1a>,当遇到第一个非十六进制的值('g')时,则数据会被截断。

Buffer.from('1a7g', 'hex');
// 打印 <Buffer 1a>,当数据以一个数字('7')结尾时,则数据会被截断。

Buffer.from('1634', 'hex');
// 打印 <Buffer 16 34>,所有数据均可用。

现代的 Web 浏览器遵循 WHATWG 编码标准,将 'latin1''ISO-8859-1' 别名为 'win-1252'。 这意味着当执行 http.get() 之类的操作时,如果返回的字符集是 WHATWG 规范中列出的字符集之一,则服务器可能实际返回 'win-1252' 编码的数据,而使用 'latin1' 编码可能错误地解码字符。

Buffer 与 TypedArray#

中英对照

Buffer 实例也是 JavaScript 的 Uint8ArrayTypedArray 实例。 所有的 TypedArray 方法在 Buffer 上也可用。 但是, Buffer 的 API 和 TypedArray 的 API 之间存在细微的不兼容。

主要表现在:

有两种方法可以从一个 Buffer 创建新的 TypedArray 实例:

  • Buffer 传给 TypedArray 的构造函数,则会拷贝 Buffer 的内容(会被解析为整数数组,而不是目标类型的字节序列)。
const buf = Buffer.from([1, 2, 3, 4]);
const uint32array = new Uint32Array(buf);

console.log(uint32array);

// 打印: Uint32Array(4) [ 1, 2, 3, 4 ]
const buf = Buffer.from('hello', 'utf16le');
const uint16arr = new Uint16Array(
  buf.buffer,
  buf.byteOffset,
  buf.length / Uint16Array.BYTES_PER_ELEMENT);

console.log(uint16array);

// 打印: Uint16Array(5) [ 104, 101, 108, 108, 111 ]

也可以通过使用 TypedArray 对象的 .buffer 属性,以相同的方式来创建一个与 TypedArray 实例共享相同分配内存的新 Buffer。 在这种情况下,Buffer.from() 的行为类似于 new Uint8Array()

const arr = new Uint16Array(2);

arr[0] = 5000;
arr[1] = 4000;

// 拷贝 `arr` 的内容。
const buf1 = Buffer.from(arr);

// 与 `arr` 共享内存。
const buf2 = Buffer.from(arr.buffer);

console.log(buf1);
// 打印: <Buffer 88 a0>
console.log(buf2);
// 打印: <Buffer 88 13 a0 0f>

arr[1] = 6000;

console.log(buf1);
// 打印: <Buffer 88 a0>
console.log(buf2);
// 打印: <Buffer 88 13 70 17>

当使用 TypedArray.buffer 创建 Buffer 时,也可以通过传入 byteOffsetlength 参数只使用底层 ArrayBuffer 的一部分。

const arr = new Uint16Array(20);
const buf = Buffer.from(arr.buffer, 0, 16);

console.log(buf.length);
// 打印: 16

Buffer.from()TypedArray.from() 有着不同的实现。 具体来说,TypedArray 可以接受第二个参数作为映射函数,在类型数组的每个元素上调用:

  • TypedArray.from(source[, mapFn[, thisArg]])

Buffer.from() 方法则不支持映射函数的使用:

Buffer 与迭代器#

中英对照

Buffer 实例可以使用 for..of 语法进行迭代:

const buf = Buffer.from([1, 2, 3]);

for (const b of buf) {
  console.log(b);
}
// 打印:
//   1
//   2
//   3

此外,buf.values()buf.keys()、和 buf.entries() 方法也可用于创建迭代器。

Buffer 类#

中英对照

Buffer 类是一个全局变量,用于直接处理二进制数据。 它可以使用多种方式构建。

Buffer.alloc(size[, fill[, encoding]])#

中英对照

分配一个大小为 size 字节的新 Buffer。 如果 fillundefined,则用零填充 Buffer

const buf = Buffer.alloc(5);

console.log(buf);
// 打印: <Buffer 00 00 00 00 00>

如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,则抛出 ERR_INVALID_OPT_VALUE

如果指定了 fill,则分配的 Buffer 通过调用 buf.fill(fill) 进行初始化。

const buf = Buffer.alloc(5, 'a');

console.log(buf);
// 打印: <Buffer 61 61 61 61 61>

如果同时指定了 fillencoding,则分配的 Buffer 通过调用 buf.fill(fill, encoding) 进行初始化 。

const buf = Buffer.alloc(11, 'aGVsbG8gd29ybGQ=', 'base64');

console.log(buf);
// 打印: <Buffer 68 65 6c 6c 6f 20 77 6f 72 6c 64>

调用 Buffer.alloc() 可能比替代的 Buffer.allocUnsafe() 慢得多,但能确保新创建的 Buffer 实例的内容永远不会包含来自先前分配的敏感数据,包括可能尚未分配给 Buffer 的数据。

如果 size 不是一个数字,则抛出 TypeError

Buffer.allocUnsafe(size)#

中英对照

  • size <integer> 新建的 Buffer 的长度。

创建一个大小为 size 字节的新 Buffer。 如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,则抛出 ERR_INVALID_OPT_VALUE

以这种方式创建的 Buffer 实例的底层内存是未初始化的。 新创建的 Buffer 的内容是未知的,可能包含敏感数据。 使用 Buffer.alloc() 可以创建以零初始化的 Buffer 实例。

const buf = Buffer.allocUnsafe(10);

console.log(buf);
// 打印(内容可能有所不同): <Buffer a0 8b 28 3f 01 00 00 00 50 32>

buf.fill(0);

console.log(buf);
// 打印: <Buffer 00 00 00 00 00 00 00 00 00 00>

如果 size 不是一个数字,则抛出 TypeError

Buffer 模块会预分配一个内部的大小为 Buffer.poolSizeBuffer 实例,作为快速分配的内存池,用于使用 Buffer.allocUnsafe() 创建新的 Buffer 实例、或 Buffer.from(array)、或 Buffer.concat()、或弃用的 new Buffer(size) 构造器但仅当 size 小于或等于 Buffer.poolSize >> 1Buffer.poolSize 除以二再向下取整)。

对这个预分配的内部内存池的使用是调用 Buffer.alloc(size, fill)Buffer.allocUnsafe(size).fill(fill) 两者之间的关键区别。 具体来说, Buffer.alloc(size, fill) 永远不会使用内部的 Buffer 池,而 Buffer.allocUnsafe(size).fill(fill)size 小于或等于 Buffer.poolSize 的一半时将会使用内部的 Buffer池。 该差异虽然很微妙,但当应用程序需要 Buffer.allocUnsafe() 提供的额外性能时,则非常重要。

Buffer.allocUnsafeSlow(size)#

中英对照

  • size <integer> 新建的 Buffer 的长度。

创建一个大小为 size 字节的新 Buffer。 如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,则抛出 ERR_INVALID_OPT_VALUE。 如果 size 为 0,则创建一个长度为零的 Buffer

以这种方式创建的 Buffer 实例的底层内存是未初始化的。 Buffer 的内容是未知的,可能包含敏感数据。 使用 buf.fill(0) 可以以零初始化 Buffer 实例。

当使用 Buffer.allocUnsafe() 创建新的 Buffer 实例时,如果要分配的内存小于 4KB,则会从一个预分配的 Buffer 切割出来。 这可以避免垃圾回收机制因创建太多独立的 Buffer 而过度使用。 通过消除跟踪和清理尽可能多的单个 ArrayBuffer 对象的需要,该方法可以提高性能和内存使用率。

当开发人员需要在内存池中保留一小块内存时,可以使用 Buffer.allocUnsafeSlow() 创建一个非内存池的 Buffer 实例并拷贝相关的比特位出来。

// 需要保留一小块内存。
const store = [];

socket.on('readable', () => {
  let data;
  while (null !== (data = readable.read())) {
    // 为剩下的数据分配内存。
    const sb = Buffer.allocUnsafeSlow(10);

    // 拷贝数据到新分配的内存。
    data.copy(sb, 0, 0, 10);

    store.push(sb);
  }
});

如果 size 不是一个数字,则抛出 TypeError

Buffer.byteLength(string[, encoding])#

中英对照

当使用 encoding 进行编码时,返回字符串的字节长度。 与 String.prototype.length 不同,后者不会考虑用于将字符串转换为字节的编码。

对于 'base64''hex',此函数会假定输入是有效的。 对于包含非 base64/hex 编码的数据(例如空格)的字符串,返回值可能是大于从字符串创建的 Buffer 的长度。

const str = '\u00bd + \u00bc = \u00be';

console.log(`${str}: ${str.length} 个字符, ` +
            `${Buffer.byteLength(str, 'utf8')} 个字节`);
// 打印: ½ + ¼ = ¾: 9 个字符, 12 个字节

string 是一个 Buffer/DataView/TypedArray/ArrayBuffer/SharedArrayBuffer 时,返回 .byteLength 报告的字节长度。

Buffer.compare(buf1, buf2)#

中英对照

比较 buf1buf2,主要用于 Buffer 实例数组的排序。 相当于调用 buf1.compare(buf2)

const buf1 = Buffer.from('1234');
const buf2 = Buffer.from('0123');
const arr = [buf1, buf2];

console.log(arr.sort(Buffer.compare));
// 打印: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ]
// (结果相当于: [buf2, buf1])

Buffer.concat(list[, totalLength])#

中英对照

返回一个合并了 list 中所有 Buffer 实例的新 Buffer

如果 list 中没有元素、或 totalLength 为 0,则返回一个长度为 0 的 Buffer

如果没有提供 totalLength,则通过将 list 中的 Buffer 实例的长度相加来计算得出。

如果提供了 totalLength,则会强制转换为无符号整数。 如果 list 中的 Buffer 合并后的总长度大于 totalLength,则结果会被截断到 totalLength 的长度。

// 用含有三个 `Buffer` 实例的数组创建一个单一的 `Buffer`。

const buf1 = Buffer.alloc(10);
const buf2 = Buffer.alloc(14);
const buf3 = Buffer.alloc(18);
const totalLength = buf1.length + buf2.length + buf3.length;

console.log(totalLength);
// 打印: 42

const bufA = Buffer.concat([buf1, buf2, buf3], totalLength);

console.log(bufA);
// 打印: <Buffer 00 00 00 00 ...>
console.log(bufA.length);
// 打印: 42

Buffer.concat() may also use the internal Buffer pool like Buffer.allocUnsafe() does.

Buffer.from(array)#

中英对照

使用 0255 范围内的字节数组 array 来分配一个新的 Buffer。 超出该范围的数组条目会被截断以适合它。

// 创建一个包含字符串 'buffer' 的 UTF-8 字节的新 Buffer。
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);

如果 array 不是一个 Array 或适用于 Buffer.from() 变量的其他类型,则抛出 TypeError

Buffer.from(array)Buffer.from(string) 也可以像 Buffer.allocUnsafe() 一样使用内部的 Buffer 池。

Buffer.from(arrayBuffer[, byteOffset[, length]])#

中英对照

创建 ArrayBuffer 的视图,但不会拷贝底层内存。 例如,当传入 TypedArray.buffer 属性的引用时,新建的 Buffer 会与 TypedArray 共享同一内存。

const arr = new Uint16Array(2);

arr[0] = 5000;
arr[1] = 4000;

// 与 `arr` 共享内存。
const buf = Buffer.from(arr.buffer);

console.log(buf);
// 打印: <Buffer 88 13 a0 0f>

// 改变原先的 Uint16Array 也会改变 Buffer。
arr[1] = 6000;

console.log(buf);
// 打印: <Buffer 88 13 70 17>

可选的 byteOffsetlength 参数指定 arrayBuffer 中与 Buffer 共享的内存范围。

const ab = new ArrayBuffer(10);
const buf = Buffer.from(ab, 0, 2);

console.log(buf.length);
// 打印: 2

如果 arrayBuffer 不是一个 ArrayBufferSharedArrayBuffer 或适用于 Buffer.from() 变量的其他类型,则抛出 TypeError

Buffer.from(buffer)#

中英对照

拷贝 buffer 的数据到新建的 Buffer 实例。

const buf1 = Buffer.from('buffer');
const buf2 = Buffer.from(buf1);

buf1[0] = 0x61;

console.log(buf1.toString());
// 打印: auffer
console.log(buf2.toString());
// 打印: buffer

如果 buffer 不是一个 Buffer 或适用于 Buffer.from() 变量的其他类型,则抛出 TypeError

Buffer.from(object[, offsetOrEncoding[, length]])#

中英对照

  • object <Object> 支持 Symbol.toPrimitivevalueOf() 的对象。
  • offsetOrEncoding <integer> | <string> 字节偏移量或字符编码。
  • length <integer> 长度。

对于 valueOf() 返回值不严格等于 object 的对象,返回 Buffer.from(object.valueOf(), offsetOrEncoding, length)

const buf = Buffer.from(new String('this is a test'));
// 打印: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>

对于支持 Symbol.toPrimitive 的对象,会返回 Buffer.from(object[Symbol.toPrimitive]('string'), offsetOrEncoding)

class Foo {
  [Symbol.toPrimitive]() {
    return 'this is a test';
  }
}

const buf = Buffer.from(new Foo(), 'utf8');
// 打印: <Buffer 74 68 69 73 20 69 73 20 61 20 74 65 73 74>

如果 object 没有提及的方法、或适用于 Buffer.from() 变量的其他类型,则抛出 TypeError

Buffer.from(string[, encoding])#

中英对照

  • string <string> 要编码的字符串。
  • encoding <string> string 的字符编码。默认值: 'utf8'

创建一个包含 string 的新 Bufferencoding 参数指定用于将 string 转换为字节的字符编码。

const buf1 = Buffer.from('this is a tést');
const buf2 = Buffer.from('7468697320697320612074c3a97374', 'hex');

console.log(buf1.toString());
// 打印: this is a tést
console.log(buf2.toString());
// 打印: this is a tést
console.log(buf1.toString('latin1'));
// 打印: this is a tést

如果 string 不是一个字符串或适用于 Buffer.from() 变量的其他类型,则抛出 TypeError

Buffer.isBuffer(obj)#

中英对照

如果 obj 是一个 Buffer,则返回 true,否则返回 false

Buffer.isEncoding(encoding)#

中英对照

如果 encoding 是支持的字符编码的名称,则返回 true,否则返回 false

console.log(Buffer.isEncoding('utf-8'));
// 打印: true

console.log(Buffer.isEncoding('hex'));
// 打印: true

console.log(Buffer.isEncoding('utf/8'));
// 打印: false

console.log(Buffer.isEncoding(''));
// 打印: false

Buffer.poolSize#

中英对照

这是用于缓冲池的预分配的内部 Buffer 实例的大小(以字节为单位)。 该值可以修改。

buf[index]#

中英对照

索引操作符 [index] 可用于获取或设置 buf 中指定的 index 位置的八位字节。 该值指向单个字节,所以有效的值的范围是 0x000xFF(十六进制)、或 0255(十进制)。

该操作符继承自 Uint8Array,所以对越界访问的行为与 Uint8Array 相同。 也就是说,当 index 为负数或大于或等于 buf.length 时,则 buf[index] 返回 undefined,而如果 index 为负数或 >= buf.length 时,则 buf[index] = value 不会修改该 buffer。

// 拷贝 ASCII 字符串到 `Buffer`,每次拷贝一个字节。
// (这仅适用于只有 ASCII 字符串。通常,应使用 `Buffer.from()` 来执行此转换。)

const str = 'http://nodejs.cn/';
const buf = Buffer.allocUnsafe(str.length);

for (let i = 0; i < str.length; i++) {
  buf[i] = str.charCodeAt(i);
}

console.log(buf.toString('utf8'));
// 打印: http://nodejs.cn/

buf.buffer#

中英对照

  • <ArrayBuffer> 创建此 Buffer 对象时基于的底层 ArrayBuffer 对象。

不能保证此 ArrayBuffer 与原始的 Buffer 完全对应。 有关详细信息,参见 buf.byteOffset 上的说明。

const arrayBuffer = new ArrayBuffer(16);
const buffer = Buffer.from(arrayBuffer);

console.log(buffer.buffer === arrayBuffer);
// 打印: true

buf.byteOffset#

中英对照

  • <integer> Buffer 底层的 ArrayBuffer 对象的 byteOffset

Buffer.from(ArrayBuffer, byteOffset, length) 设置了 byteOffset 或创建一个小于 Buffer.poolSizeBuffer 时,底层的 ArrayBuffer 的偏移量并不是从 0 开始。

当直接使用 buf.buffer 访问底层的 ArrayBuffer 时可能会导致问题,因为 ArrayBuffer 的其他部分可能并不指向 Buffer 对象。

当创建与 Buffer 共享其内存的 TypedArray 对象时,需要正确地指定 byteOffset

// 创建一个小于 `Buffer.poolSize` 的 buffer。
const nodeBuffer = new Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);

// 当将 Node.js Buffer 转换为 Int8Array 时,
// 应使用 byteOffset 仅引用 `nodeBuffer.buffer` 中包含 `nodeBuffer` 内存的部分。
new Int8Array(nodeBuffer.buffer, nodeBuffer.byteOffset, nodeBuffer.length);

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]])#

中英对照

  • target <Buffer> | <Uint8Array> 要与 buf 对比的 BufferUint8Array
  • targetStart <integer> target 中开始对比的偏移量。默认值: 0
  • targetEnd <integer> target 中结束对比的偏移量(不包含)。默认值: target.length
  • sourceStart <integer> buf 中开始对比的偏移量。默认值: 0
  • sourceEnd <integer> buf 中结束对比的偏移量(不包含)。默认值: buf.length
  • 返回: <integer>

对比 buftarget,并返回一个数值,表明 buf 在排序上是否排在 target 前面、或后面、或相同。 对比是基于各自 Buffer 实际的字节序列。

  • 如果 targetbuf 相同,则返回 0
  • 如果 target 排在 buf 前面,则返回 1
  • 如果 target 排在 buf 后面,则返回 -1
const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('BCD');
const buf3 = Buffer.from('ABCD');

console.log(buf1.compare(buf1));
// 打印: 0
console.log(buf1.compare(buf2));
// 打印: -1
console.log(buf1.compare(buf3));
// 打印: -1
console.log(buf2.compare(buf1));
// 打印: 1
console.log(buf2.compare(buf3));
// 打印: 1
console.log([buf1, buf2, buf3].sort(Buffer.compare));
// 打印: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ]
// (相当于: [buf1, buf3, buf2])

targetStarttargetEndsourceStartsourceEnd 可用于指定 targetbuf 中对比的范围。

const buf1 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9]);
const buf2 = Buffer.from([5, 6, 7, 8, 9, 1, 2, 3, 4]);

console.log(buf1.compare(buf2, 5, 9, 0, 4));
// 打印: 0
console.log(buf1.compare(buf2, 0, 6, 4));
// 打印: -1
console.log(buf1.compare(buf2, 5, 6, 5));
// 打印: 1

如果 targetStart < 0sourceStart < 0targetEnd > target.byteLengthsourceEnd > source.byteLength,则抛出 ERR_OUT_OF_RANGE

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]])#

中英对照

拷贝 buf 中某个区域的数据到 target 中的某个区域,即使 target 的内存区域与 buf 的重叠。

TypedArray#set() 执行相同的操作,并且可用于所有的 TypedArray,包括 Node.js 的 Buffer,尽管它采用不同的函数参数。

// 创建两个 `Buffer` 实例。
const buf1 = Buffer.allocUnsafe(26);
const buf2 = Buffer.allocUnsafe(26).fill('!');

for (let i = 0; i < 26; i++) {
  // 97 是 'a' 的十进制 ASCII 值。
  buf1[i] = i + 97;
}

// 拷贝 `buf1` 中第 16 至 19 字节偏移量的数据到 `buf2` 第 8 字节偏移量开始。
buf1.copy(buf2, 8, 16, 20);
// 这等效于:
// buf2.set(buf1.subarray(16, 20), 8);

console.log(buf2.toString('ascii', 0, 25));
// 打印: !!!!!!!!qrst!!!!!!!!!!!!!
// 创建一个 `Buffer`,并拷贝同一 `Buffer` 中一个区域的数据到另一个重叠的区域。

const buf = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 是 'a' 的十进制 ASCII 值。
  buf[i] = i + 97;
}

buf.copy(buf, 0, 4, 10);

console.log(buf.toString());
// 打印: efghijghijklmnopqrstuvwxyz

buf.entries()#

中英对照

buf 的内容创建并返回一个 [index, byte] 形式的迭代器

// 记录 `Buffer` 的全部内容。

const buf = Buffer.from('buffer');

for (const pair of buf.entries()) {
  console.log(pair);
}
// 打印:
//   [0, 98]
//   [1, 117]
//   [2, 102]
//   [3, 102]
//   [4, 101]
//   [5, 114]

buf.equals(otherBuffer)#

中英对照

如果 bufotherBuffer 具有完全相同的字节,则返回 true,否则返回 false。 相当于 buf.compare(otherBuffer) === 0

const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('414243', 'hex');
const buf3 = Buffer.from('ABCD');

console.log(buf1.equals(buf2));
// 打印: true
console.log(buf1.equals(buf3));
// 打印: false

buf.fill(value[, offset[, end]][, encoding])#

中英对照

用指定的 value 填充 buf。 如果没有指定 offsetend,则填充整个 buf

// 用 ASCII 字符 'h' 填充 `Buffer`。

const b = Buffer.allocUnsafe(50).fill('h');

console.log(b.toString());
// 打印: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

如果 value 不是字符串、 Buffer、或整数,则会被转换为 uint32 值。 如果得到的整数大于 255(十进制),则 buf 将会使用 value & 255 填充。

如果 fill() 最后写入的是一个多字节字符,则只写入适合 buf 的字节:

// 使用在 UTF-8 中占用两个字节的字符来填充 `Buffer`。

console.log(Buffer.allocUnsafe(5).fill('\u0222'));
// 打印: <Buffer c8 a2 c8 a2 c8>

如果 value 包含无效的字符,则截掉无效的字符。 如果截掉后没有数据,则不填充:

const buf = Buffer.allocUnsafe(5);

console.log(buf.fill('a'));
// 打印: <Buffer 61 61 61 61 61>
console.log(buf.fill('aazz', 'hex'));
// 打印: <Buffer aa aa aa aa aa>
console.log(buf.fill('zz', 'hex'));
// 抛出异常。

buf.includes(value[, byteOffset][, encoding])#

中英对照

  • value <string> | <Buffer> | <Uint8Array> | <integer> 要查找的值。
  • byteOffset <integer> buf 中开始查找的偏移量。默认值: 0
  • encoding <string> 如果 value 是字符串,则指定 value 的字符编码。默认值: 'utf8'
  • 返回: <boolean> 如果 buf 查找到 value,则返回 true,否则返回 false

相当于 buf.indexOf() !== -1

const buf = Buffer.from('this is a buffer');

console.log(buf.includes('this'));
// 打印: true
console.log(buf.includes('is'));
// 打印: true
console.log(buf.includes(Buffer.from('a buffer')));
// 打印: true
console.log(buf.includes(97));
// 打印: true(97 是 'a' 的十进制 ASCII 值)
console.log(buf.includes(Buffer.from('a buffer example')));
// 打印: false
console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8)));
// 打印: true
console.log(buf.includes('this', 4));
// 打印: false

buf.indexOf(value[, byteOffset][, encoding])#

中英对照

  • value <string> | <Buffer> | <Uint8Array> | <integer> 要查找的值。
  • byteOffset <integer> buf 中开始查找的偏移量。默认值: 0
  • encoding <string> 如果 value 是字符串,则指定 value 的字符编码。默认值: 'utf8'
  • 返回: <integer> buf 中首次出现 value 的索引,如果 buf 没包含 value 则返回 -1

如果 value 是:

  • 一个字符串,则 value 根据 encoding 的字符编码进行解析。
  • 一个 BufferUint8Array,则 value 会整个进行对比。如果要对比部分 Buffer,可使用 buf.slice()
  • 一个数值, 则 value 会被解析成 0255 之间的无符号八位整数值。
const buf = Buffer.from('this is a buffer');

console.log(buf.indexOf('this'));
// 打印: 0
console.log(buf.indexOf('is'));
// 打印: 2
console.log(buf.indexOf(Buffer.from('a buffer')));
// 打印: 8
console.log(buf.indexOf(97));
// 打印: 8(97 是 'a' 的十进制 ASCII 值)
console.log(buf.indexOf(Buffer.from('a buffer example')));
// 打印: -1
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8)));
// 打印: 8

const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le');

console.log(utf16Buffer.indexOf('\u03a3', 0, 'utf16le'));
// 打印: 4
console.log(utf16Buffer.indexOf('\u03a3', -4, 'utf16le'));
// 打印: 6

如果 value 不是一个字符串、数值、或 Buffer,则此方法将会抛出 TypeError。 如果 value 是一个数值,则会被转换成介于 0 到 255 之间的整数值。

如果 byteOffset 不是一个数值,则会被转换成数值。 如果转换后的值为 NaN0, 则会查找整个 buffer。 这与 String#indexOf() 是一致的。

const b = Buffer.from('abcdef');

// 传入一个数值,但不是有效的字节。
// 打印:2,相当于查找 99 或 'c'。
console.log(b.indexOf(99.9));
console.log(b.indexOf(256 + 99));

// 传入被转换成 NaN 或 0 的 byteOffset。
// 打印:1,查找整个 buffer。
console.log(b.indexOf('b', undefined));
console.log(b.indexOf('b', {}));
console.log(b.indexOf('b', null));
console.log(b.indexOf('b', []));

如果 value 是一个空字符串或空 Buffer,且 byteOffset 小于 buf.length,则返回 byteOffset。 如果 value 是一个空字符串,且 byteOffset 大于或等于 buf.length,则返回 buf.length

buf.keys()#

中英对照

创建并返回 buf 键名(索引)的迭代器

const buf = Buffer.from('buffer');

for (const key of buf.keys()) {
  console.log(key);
}
// 打印:
//   0
//   1
//   2
//   3
//   4
//   5

buf.lastIndexOf(value[, byteOffset][, encoding])#

中英对照

  • value <string> | <Buffer> | <Uint8Array> | <integer> 要查找的值。
  • byteOffset <integer> buf 中开始查找的偏移量。默认值: buf.length - 1
  • encoding <string> 如果 value 是字符串,则指定 value 的字符编码。默认值: 'utf8'
  • 返回: <integer> buf 中最后一次出现 value 的索引,如果 buf 没包含 value 则返回 -1

buf.indexOf() 的区别是,查找的是 value 最后一次出现的索引,而不是首次出现。

const buf = Buffer.from('this buffer is a buffer');

console.log(buf.lastIndexOf('this'));
// 打印: 0
console.log(buf.lastIndexOf('buffer'));
// 打印: 17
console.log(buf.lastIndexOf(Buffer.from('buffer')));
// 打印: 17
console.log(buf.lastIndexOf(97));
// 打印: 15(97 是 'a' 的十进制 ASCII 值)
console.log(buf.lastIndexOf(Buffer.from('yolo')));
// 打印: -1
console.log(buf.lastIndexOf('buffer', 5));
// 打印: 5
console.log(buf.lastIndexOf('buffer', 4));
// 打印: -1

const utf16Buffer = Buffer.from('\u039a\u0391\u03a3\u03a3\u0395', 'utf16le');

console.log(utf16Buffer.lastIndexOf('\u03a3', undefined, 'utf16le'));
// 打印: 6
console.log(utf16Buffer.lastIndexOf('\u03a3', -5, 'utf16le'));
// 打印: 4

如果 value 不是一个字符串、数字、或 Buffer,则此方法将会抛出 TypeError。 如果 value 是一个数值,则它将会被强制转换成一个有效的字节值,即一个 0 到 255 之间的整数。

如果 byteOffset 不是一个数值,则会被转换成数值。 如果转换后的值为 NaN,比如 {}undefined,则会查找整个 buffer。 这与 String#lastIndexOf() 是一致的。

const b = Buffer.from('abcdef');

// 传入一个数值,但不是一个有效的字节。
// 输出:2,相当于查找 99 或 'c'。
console.log(b.lastIndexOf(99.9));
console.log(b.lastIndexOf(256 + 99));

// 传入被转换成 NaN 的 byteOffset。
// 输出:1,查找整个 buffer。
console.log(b.lastIndexOf('b', undefined));
console.log(b.lastIndexOf('b', {}));

// 传入被转换成 0 的 byteOffset。
// 输出:-1,相当于传入 0。
console.log(b.lastIndexOf('b', null));
console.log(b.lastIndexOf('b', []));

如果 value 是一个空字符串或空 Buffer,则返回 byteOffset

buf.length#

中英对照

返回 buf 中的字节数。

// 创建一个 `Buffer`,并使用 UTF-8 写入一个短的字符串。

const buf = Buffer.alloc(1234);

console.log(buf.length);
// 打印: 1234

buf.write('http://nodejs.cn/', 0, 'utf8');

console.log(buf.length);
// 打印: 1234

buf.parent#

稳定性: 0 - 弃用: 改为使用 buf.buffer

The buf.parent property is a deprecated alias for buf.buffer.

buf.readBigInt64BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <bigint>

buf 中指定的 offset 读取一个有符号大端序的 64 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

buf.readBigInt64LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <bigint>

buf 中指定的 offset 读取一个有符号小端序的 64 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

buf.readBigUInt64BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <bigint>

buf 中指定的 offset 读取一个无符号大端序的 64 位整数值。

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64BE(0));
// 打印: 4294967295n

buf.readBigUInt64LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <bigint>

buf 中指定的 offset 读取一个无符号小端序的 64 位整数值。

const buf = Buffer.from([0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff]);

console.log(buf.readBigUInt64LE(0));
// 打印: 18446744069414584320n

buf.readDoubleBE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <number>

buf 中指定的 offset 读取一个 64 位的大端序双精度值。

const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);

console.log(buf.readDoubleBE(0));
// 打印: 8.20788039913184e-304

buf.readDoubleLE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <number>

buf 中指定的 offset 读取一个 64 位的小端序双精度值。

const buf = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8]);

console.log(buf.readDoubleLE(0));
// 打印: 5.447603722011605e-270
console.log(buf.readDoubleLE(1));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readFloatBE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <number>

buf 中指定的 offset 读取一个 32 位的大端序浮点值。

const buf = Buffer.from([1, 2, 3, 4]);

console.log(buf.readFloatBE(0));
// 打印: 2.387939260590663e-38

buf.readFloatLE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <number>

buf 中指定的 offset 读取一个 32 位的小端序浮点值。

const buf = Buffer.from([1, 2, 3, 4]);

console.log(buf.readFloatLE(0));
// 打印: 1.539989614439558e-36
console.log(buf.readFloatLE(1));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readInt8([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 1默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个有符号的 8 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

const buf = Buffer.from([-1, 5]);

console.log(buf.readInt8(0));
// 打印: -1
console.log(buf.readInt8(1));
// 打印: 5
console.log(buf.readInt8(2));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readInt16BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个有符号大端序的 16 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16BE(0));
// 打印: 5

buf.readInt16LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个有符号小端序的 16 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

const buf = Buffer.from([0, 5]);

console.log(buf.readInt16LE(0));
// 打印: 1280
console.log(buf.readInt16LE(1));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readInt32BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个有符号大端序的 32 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

const buf = Buffer.from([0, 0, 0, 5]);

console.log(buf.readInt32BE(0));
// 打印: 5

buf.readInt32LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个有符号小端序的 32 位整数值。

Buffer 中读取的整数值会被解析为二进制补码值。

const buf = Buffer.from([0, 0, 0, 5]);

console.log(buf.readInt32LE(0));
// 打印: 83886080
console.log(buf.readInt32LE(1));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readIntBE(offset, byteLength)#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要读取的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer>

buf 中指定的 offset 读取 byteLength 个字节,并将读取的值解析为大端序的二进制补码值,最高支持 48 位精度。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readIntBE(0, 6).toString(16));
// 打印: 1234567890ab
console.log(buf.readIntBE(1, 6).toString(16));
// 抛出异常 ERR_OUT_OF_RANGE。
console.log(buf.readIntBE(1, 0).toString(16));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readIntLE(offset, byteLength)#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要读取的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer>

buf 中指定的 offset 读取 byteLength 个字节,并将读取的值解析为小端序的二进制补码值,最高支持 48 位精度。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readIntLE(0, 6).toString(16));
// 打印: -546f87a9cbee

buf.readUInt8([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 1默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个无符号的 8 位整数值。

const buf = Buffer.from([1, -2]);

console.log(buf.readUInt8(0));
// 打印: 1
console.log(buf.readUInt8(1));
// 打印: 254
console.log(buf.readUInt8(2));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readUInt16BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个无符号大端序的 16 位整数值。

const buf = Buffer.from([0x12, 0x34, 0x56]);

console.log(buf.readUInt16BE(0).toString(16));
// 打印: 1234
console.log(buf.readUInt16BE(1).toString(16));
// 打印: 3456

buf.readUInt16LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个无符号小端序的 16 位整数值。

const buf = Buffer.from([0x12, 0x34, 0x56]);

console.log(buf.readUInt16LE(0).toString(16));
// 打印: 3412
console.log(buf.readUInt16LE(1).toString(16));
// 打印: 5634
console.log(buf.readUInt16LE(2).toString(16));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readUInt32BE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个无符号大端序的 32 位整数值。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]);

console.log(buf.readUInt32BE(0).toString(16));
// 打印: 12345678

buf.readUInt32LE([offset])#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer>

buf 中指定的 offset 读取一个无符号小端序的 32 位整数值。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78]);

console.log(buf.readUInt32LE(0).toString(16));
// 打印: 78563412
console.log(buf.readUInt32LE(1).toString(16));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readUIntBE(offset, byteLength)#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要读取的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer>

buf 中指定的 offset 读取 byteLength 个字节,并将读取的值解析为无符号大端序的整数,最高支持 48 位精度。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readUIntBE(0, 6).toString(16));
// 打印: 1234567890ab
console.log(buf.readUIntBE(1, 6).toString(16));
// 抛出异常 ERR_OUT_OF_RANGE。

buf.readUIntLE(offset, byteLength)#

中英对照

  • offset <integer> 开始读取之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要读取的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer>

buf 中指定的 offset 读取 byteLength 个字节,并将读取的值解析为无符号小端序的整数,最高支持 48 位精度。

const buf = Buffer.from([0x12, 0x34, 0x56, 0x78, 0x90, 0xab]);

console.log(buf.readUIntLE(0, 6).toString(16));
// 打印: ab9078563412

buf.subarray([start[, end]])#

中英对照

返回一个新的 Buffer,它引用与原始的 Buffer 相同的内存,但是由 startend 索引进行偏移和裁剪。

指定大于 buf.lengthend 将会返回与 end 等于 buf.length 时相同的结果。

此方法继承自 TypedArray#subarray()

修改新的 Buffer 切片将会修改原始 Buffer 中的内存,因为两个对象分配的内存是重叠的。

// 使用 ASCII 字母创建一个 `Buffer`,然后进行切片,再修改原始 `Buffer` 中的一个字节。

const buf1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 是 'a' 的十进制 ASCII 值。
  buf1[i] = i + 97;
}

const buf2 = buf1.subarray(0, 3);

console.log(buf2.toString('ascii', 0, buf2.length));
// 打印: abc

buf1[0] = 33;

console.log(buf2.toString('ascii', 0, buf2.length));
// 打印: !bc

指定负的索引会导致切片的生成是相对于 buf 的末尾而不是开头。

const buf = Buffer.from('buffer');

console.log(buf.subarray(-6, -1).toString());
// 打印: buffe
// (相当于 buf.subarray(0, 5)。)

console.log(buf.subarray(-6, -2).toString());
// 打印: buff
// (相当于 buf.subarray(0, 4)。)

console.log(buf.subarray(-5, -2).toString());
// 打印: uff
// (相当于 buf.subarray(1, 4)。)

buf.slice([start[, end]])#

中英对照

返回一个新的 Buffer,它引用与原始的 Buffer 相同的内存,但是由 startend 索引进行偏移和裁剪。

这与 buf.subarray() 的行为相同。

此方法与 Uint8Array.prototype.slice() 不兼容,后者是 Buffer 的超类。 若要复制切片,则使用 Uint8Array.prototype.slice()

const buf = Buffer.from('buffer');

const copiedBuf = Uint8Array.prototype.slice.call(buf);
copiedBuf[0]++;
console.log(copiedBuf.toString());
// 打印: cuffer

console.log(buf.toString());
// 打印: buffer

buf.swap16()#

中英对照

buf 解析成无符号的 16 位整数的数组,并且以字节顺序原地进行交换。 如果 buf.length 不是 2 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// 打印: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap16();

console.log(buf1);
// 打印: <Buffer 02 01 04 03 06 05 08 07>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap16();
// 抛出异常 ERR_INVALID_BUFFER_SIZE。

buf.swap16() 的一个方便用途是在 UTF-16 小端序和 UTF-16 大端序之间执行快速的原地转换:

const buf = Buffer.from('This is little-endian UTF-16', 'utf16le');
buf.swap16(); // 转换为大端序 UTF-16 文本。

buf.swap32()#

中英对照

buf 解析成无符号的 32 位整数的数组,并且以字节顺序原地进行交换。 如果 buf.length 不是 4 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// 打印: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap32();

console.log(buf1);
// 打印: <Buffer 04 03 02 01 08 07 06 05>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap32();
// 抛出异常 ERR_INVALID_BUFFER_SIZE。

buf.swap64()#

中英对照

buf 解析成 64 位数值的数组,并且以字节顺序原地进行交换。 如果 buf.length 不是 8 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE

const buf1 = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8]);

console.log(buf1);
// 打印: <Buffer 01 02 03 04 05 06 07 08>

buf1.swap64();

console.log(buf1);
// 打印: <Buffer 08 07 06 05 04 03 02 01>

const buf2 = Buffer.from([0x1, 0x2, 0x3]);

buf2.swap64();
// 抛出异常 ERR_INVALID_BUFFER_SIZE。

buf.toJSON()#

中英对照

返回 buf 的 JSON 格式。 当字符串化 Buffer 实例时,JSON.stringify() 会调用该函数。

Buffer.from() 接受此方法返回的格式的对象。 特别是, Buffer.from(buf.toJSON()) 的工作方式类似于 Buffer.from(buf)

const buf = Buffer.from([0x1, 0x2, 0x3, 0x4, 0x5]);
const json = JSON.stringify(buf);

console.log(json);
// 打印: {"type":"Buffer","data":[1,2,3,4,5]}

const copy = JSON.parse(json, (key, value) => {
  return value && value.type === 'Buffer' ?
    Buffer.from(value) :
    value;
});

console.log(copy);
// 打印: <Buffer 01 02 03 04 05>

buf.toString([encoding[, start[, end]]])#

中英对照

  • encoding <string> 使用的字符编码。默认值: 'utf8'
  • start <integer> 开始解码的字节偏移量。默认值: 0
  • end <integer> 结束解码的字节偏移量(不包含)。默认值: buf.length
  • 返回: <string>

根据 encoding 指定的字符编码将 buf 解码成字符串。 传入 startend 可以只解码 buf 的子集。

如果 encoding'utf8',并且输入中的字节序列不是有效的 UTF-8,则每个无效的字节都会由替换字符 U+FFFD 替换。

字符串的最大长度(以 UTF-16 为单位)可查看 buffer.constants.MAX_STRING_LENGTH

const buf1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 是 'a' 的十进制 ASCII 值。
  buf1[i] = i + 97;
}

console.log(buf1.toString('utf8'));
// 打印: abcdefghijklmnopqrstuvwxyz
console.log(buf1.toString('utf8', 0, 5));
// 打印: abcde

const buf2 = Buffer.from('tést');

console.log(buf2.toString('hex'));
// 打印: 74c3a97374
console.log(buf2.toString('utf8', 0, 3));
// 打印: té
console.log(buf2.toString(undefined, 0, 3));
// 打印: té

buf.values()#

中英对照

创建并返回 buf 键值(字节)的迭代器。 当对 Buffer 使用 for..of 时会调用该函数。

const buf = Buffer.from('buffer');

for (const value of buf.values()) {
  console.log(value);
}
// 打印:
//   98
//   117
//   102
//   102
//   101
//   114

for (const value of buf) {
  console.log(value);
}
// 打印:
//   98
//   117
//   102
//   102
//   101
//   114

buf.write(string[, offset[, length]][, encoding])#

中英对照

  • string <string> 要写入 buf 的字符串。
  • offset <integer> 开始写入 string 之前要跳过的字节数。默认值: 0
  • length <integer> 要写入的最大字节数(写入的字节数不会超出 buf.length - offset)。默认值: buf.length - offset
  • encoding <string> string 的字符编码。默认值: 'utf8'
  • 返回: <integer> 已写入的字节数。

根据 encoding 指定的字符编码将 string 写入到 buf 中的 offset 位置。 length 参数是要写入的字节数。 如果 buf 没有足够的空间保存整个字符串,则只会写入 string 的一部分。 只编码了一部分的字符不会被写入。

const buf = Buffer.alloc(256);

const len = buf.write('\u00bd + \u00bc = \u00be', 0);

console.log(`${len} 个字节: ${buf.toString('utf8', 0, len)}`);
// 打印: 12 个字节: ½ + ¼ = ¾

const buffer = Buffer.alloc(10);

const length = buffer.write('abcd', 8);

console.log(`${length} bytes: ${buffer.toString('utf8', 8, 10)}`);
// 打印: 2 个字节 : ab

buf.writeBigInt64BE(value[, offset])#

中英对照

  • value <bigint> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。

value 会被解析并写入为二进制补码的有符号整数。

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64BE(0x0102030405060708n, 0);

console.log(buf);
// 打印: <Buffer 01 02 03 04 05 06 07 08>

buf.writeBigInt64LE(value[, offset])#

中英对照

  • value <bigint> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。

value 会被解析并写入为二进制补码的有符号整数。

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64LE(0x0102030405060708n, 0);

console.log(buf);
// 打印: <Buffer 08 07 06 05 04 03 02 01>

buf.writeBigUInt64BE(value[, offset])#

中英对照

  • value <bigint> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64BE(0xdecafafecacefaden, 0);

console.log(buf);
// 打印: <Buffer de ca fa fe ca ce fa de>

buf.writeBigUInt64LE(value[, offset])#

中英对照

  • value <bigint> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64LE(0xdecafafecacefaden, 0);

console.log(buf);
// 打印: <Buffer de fa ce ca fe fa ca de>

buf.writeDoubleBE(value[, offset])#

中英对照

  • value <number> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是 JavaScript 数值。 当 value 不是 JavaScript 数值时,行为是未定义的。

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleBE(123.456, 0);

console.log(buf);
// 打印: <Buffer 40 5e dd 2f 1a 9f be 77>

buf.writeDoubleLE(value[, offset])#

中英对照

  • value <number> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 8默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是 JavaScript 数值。 当 value 不是 JavaScript 数值时,行为是未定义的。

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleLE(123.456, 0);

console.log(buf);
// 打印: <Buffer 77 be 9f 1a 2f dd 5e 40>

buf.writeFloatBE(value[, offset])#

中英对照

  • value <number> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是 JavaScript 数值。 当 value 不是 JavaScript 数值时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeFloatBE(0xcafebabe, 0);

console.log(buf);
// 打印: <Buffer 4f 4a fe bb>

buf.writeFloatLE(value[, offset])#

中英对照

  • value <number> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是 JavaScript 数值。 当 value 不是 JavaScript 数值时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeFloatLE(0xcafebabe, 0);

console.log(buf);
// 打印: <Buffer bb fe 4a 4f>

buf.writeInt8(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 1默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 写入到 buf 中指定的 offset 位置。 value 必须是有符号的 8 位整数。 当 value 不是有符号的 8 位整数时,行为是未定义的。

value 会被解析并写入为二进制补码的有符号整数。

const buf = Buffer.allocUnsafe(2);

buf.writeInt8(2, 0);
buf.writeInt8(-2, 1);

console.log(buf);
// 打印: <Buffer 02 fe>

buf.writeInt16BE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是有符号的 16 位整数。 当 value 不是有符号的 16 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(2);

buf.writeInt16BE(0x0102, 0);

console.log(buf);
// 打印: <Buffer 01 02>

buf.writeInt16LE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是有符号的 16 位整数。 当 value 不是有符号的 16 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(2);

buf.writeInt16LE(0x0304, 0);

console.log(buf);
// 打印: <Buffer 04 03>

buf.writeInt32BE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是有符号的 32 位整数。 当 value 不是有符号的 32 位整数,行为是未定义的。

value 会被解析并写入为二进制补码的有符号整数。

const buf = Buffer.allocUnsafe(4);

buf.writeInt32BE(0x01020304, 0);

console.log(buf);
// 打印: <Buffer 01 02 03 04>

buf.writeInt32LE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是有符号的 32 位整数。 当 value 不是有符号的 32 位整数,行为是未定义的。

value 会被解析并写入为二进制补码的有符号整数。

const buf = Buffer.allocUnsafe(4);

buf.writeInt32LE(0x05060708, 0);

console.log(buf);
// 打印: <Buffer 08 07 06 05>

buf.writeIntBE(value, offset, byteLength)#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要写入的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer> offset 加上已写入的字节数。

value 中的 byteLength 个字节作为大端序写入到 buf 中指定的 offset 位置。 最高支持 48 位精度。 当 value 不是有符号的整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(6);

buf.writeIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// 打印: <Buffer 12 34 56 78 90 ab>

buf.writeIntLE(value, offset, byteLength)#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要写入的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer> offset 加上已写入的字节数。

value 中的 byteLength 个字节作为小端序写入到 buf 中指定的 offset 位置。 最高支持 48 位精度。 当 value 不是有符号的整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(6);

buf.writeIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// 打印: <Buffer ab 90 78 56 34 12>

buf.writeUInt8(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 1默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 写入到 buf 中指定的 offset 位置。 value 必须是无符号的 8 位整数。 当 value 不是无符号的 8 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeUInt8(0x3, 0);
buf.writeUInt8(0x4, 1);
buf.writeUInt8(0x23, 2);
buf.writeUInt8(0x42, 3);

console.log(buf);
// 打印: <Buffer 03 04 23 42>

buf.writeUInt16BE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是无符号的 16 位整数。 当 value 不是无符号的 16 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16BE(0xdead, 0);
buf.writeUInt16BE(0xbeef, 2);

console.log(buf);
// 打印: <Buffer de ad be ef>

buf.writeUInt16LE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 2默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是无符号的 16 位整数。 当 value 不是无符号的 16 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeUInt16LE(0xdead, 0);
buf.writeUInt16LE(0xbeef, 2);

console.log(buf);
// 打印: <Buffer ad de ef be>

buf.writeUInt32BE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为大端序写入到 buf 中指定的 offset 位置。 value 必须是无符号的 32 位整数。 当 value 不是无符号的 32 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32BE(0xfeedface, 0);

console.log(buf);
// 打印: <Buffer fe ed fa ce>

buf.writeUInt32LE(value[, offset])#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - 4默认值: 0
  • 返回: <integer> offset 加上已写入的字节数。

value 作为小端序写入到 buf 中指定的 offset 位置。 value 必须是无符号的 32 位整数。 当 value 不是无符号的 32 位整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32LE(0xfeedface, 0);

console.log(buf);
// 打印: <Buffer ce fa ed fe>

buf.writeUIntBE(value, offset, byteLength)#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要写入的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer> offset 加上已写入的字节数。

value 中的 byteLength 个字节作为大端序写入到 buf 中指定的 offset 位置。 最高支持 48 位精度。 当 value 不是无符号的整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(6);

buf.writeUIntBE(0x1234567890ab, 0, 6);

console.log(buf);
// 打印: <Buffer 12 34 56 78 90 ab>

buf.writeUIntLE(value, offset, byteLength)#

中英对照

  • value <integer> 要写入 buf 的数值。
  • offset <integer> 开始写入之前要跳过的字节数。必须满足:0 <= offset <= buf.length - byteLength
  • byteLength <integer> 要写入的字节数。必须满足:0 < byteLength <= 6
  • 返回: <integer> offset 加上已写入的字节数。

value 中的 byteLength 个字节作为小端序写入到 buf 中指定的 offset 位置。 最高支持 48 位精度。 当 value 不是无符号的整数时,行为是未定义的。

const buf = Buffer.allocUnsafe(6);

buf.writeUIntLE(0x1234567890ab, 0, 6);

console.log(buf);
// 打印: <Buffer ab 90 78 56 34 12>

new Buffer(array)#

稳定性: 0 - 弃用: 改为使用 Buffer.from(array)

See Buffer.from(array).

new Buffer(arrayBuffer[, byteOffset[, length]])#

See Buffer.from(arrayBuffer[, byteOffset[, length]]).

new Buffer(buffer)#

稳定性: 0 - 弃用: 改为使用 Buffer.from(buffer)

See Buffer.from(buffer).

new Buffer(size)#

稳定性: 0 - 弃用: 改为使用 Buffer.alloc() (或 Buffer.allocUnsafe())。

  • size <integer> The desired length of the new Buffer.

See Buffer.alloc() and Buffer.allocUnsafe(). This variant of the constructor is equivalent to Buffer.alloc().

new Buffer(string[, encoding])#

  • string <string> String to encode.
  • encoding <string> The encoding of string. Default: 'utf8'.

See Buffer.from(string[, encoding]).

buffer 模块 API#

While, the Buffer object is available as a global, there are additional Buffer-related APIs that are available only via the buffer module accessed using require('buffer').

buffer.INSPECT_MAX_BYTES#

中英对照

返回当调用 buf.inspect() 时将会返回的最大字节数。 这可以被用户模块重写。 有关 buf.inspect() 行为的更多详细信息,参见 util.inspect()

buffer.kMaxLength#

中英对照

  • <integer> 分配给单个 Buffer 实例的最大内存。

buffer.constants.MAX_LENGTH 的别名。

buffer.transcode(source, fromEnc, toEnc)#

中英对照

将指定的 BufferUint8Array 实例从一个字符编码重新编码到另一个字符。 返回新的 Buffer 实例。

如果 fromEnctoEnc 指定了无效的字符编码,或者无法从 fromEnc 转换为 toEnc,则抛出异常。

buffer.transcode() 支持的字符编码有 'ascii''utf8''utf16le''ucs2''latin1''binary'

如果指定的字节序列无法用目标字符编码表示,则转码过程会使用替代的字符。 例如:

const buffer = require('buffer');

const newBuf = buffer.transcode(Buffer.from('€'), 'utf8', 'ascii');
console.log(newBuf.toString('ascii'));
// 打印: '?'

因为欧元符号()无法在 US-ASCII 中表示,所以在转码 Buffer 时使用 ? 代替。

SlowBuffer 类#

稳定性: 0 - 弃用: 改为使用 Buffer.allocUnsafeSlow()

See Buffer.allocUnsafeSlow(). This was never a class in the sense that the constructor always returned a Buffer instance, rather than a SlowBuffer instance.

new SlowBuffer(size)#

稳定性: 0 - 弃用: 改为使用 Buffer.allocUnsafeSlow()

  • size <integer> The desired length of the new SlowBuffer.

See Buffer.allocUnsafeSlow().

Buffer 常量#

buffer.constants.MAX_LENGTH#

中英对照

  • <integer> 单个 Buffer 实例允许的最大内存。

在 32 位的架构上,该值当前是 230 - 1 (~1GB)。 在 64 位的架构上,该值当前是 231 - 1 (~2GB)。

也可使用 buffer.kMaxLength

buffer.constants.MAX_STRING_LENGTH#

中英对照

  • <integer> 单个 string 实例允许的最大长度。

表示 string 原始数据类型能有的最大 length,以 UTF-16 代码为单位。

该值取决于使用的 JS 引擎。

Buffer.from()、Buffer.alloc() 与 Buffer.allocUnsafe()#

中英对照

在 6.0.0 之前的 Node.js 版本中, Buffer 实例是使用 Buffer 构造函数创建的,该函数根据提供的参数以不同方式分配返回的 Buffer

  • 将数字作为第一个参数传给 Buffer()(例如 new Buffer(10))会分配一个指定大小的新建的 Buffer 对象。 在 Node.js 8.0.0 之前,为此类 Buffer 实例分配的内存是未初始化的,并且可能包含敏感数据。 此类 Buffer 实例随后必须被初始化,在从 Buffer 读取数据之前,可以使用 buf.fill(0) 或写满整个 Buffer。 虽然这种行为是为了提高性能,但开发经验表明,创建一个快速但未初始化的 Buffer 与创建一个速度更慢但更安全的 Buffer 之间需要有更明确的区分。 从 Node.js 8.0.0 开始, Buffer(num)new Buffer(num) 将返回已初始化内存的 Buffer
  • 传入字符串、数组、或 Buffer 作为第一个参数,则会将传入的对象的数据拷贝到 Buffer 中。
  • 传入 ArrayBufferSharedArrayBuffer,则返回一个与给定的数组 buffer 共享已分配内存的 Buffer

由于 new Buffer() 的行为因第一个参数的类型而异,因此当未执行参数验证或 Buffer 初始化时,可能会无意中将安全性和可靠性问题引入应用程序。

例如,如果攻击者可以使应用程序接收到数字(实际期望的是字符串),则应用程序可能调用 new Buffer(100) 而不是 new Buffer("100"),使其分配一个 100 个字节的 buffer 而不是分配一个内容为 “100” 的 3 个字节的 buffer。 使用 JSON API 调用时,是非常有可能发生这种情况的。 由于 JSON 区分数字和字符串类型,因此它允许在未充分验证其输入的简单写入的应用程序可能期望始终接收字符串的情况下注入数字。 在 Node.js 8.0.0 之前,100 个字节的 buffer 可能包含任意预先存在的内存数据,因此可能会用于向远程攻击者暴露内存中的机密。 从 Node.js 8.0.0 开始,由于数据会用零填充,因此不会发生内存暴露。 但是,其他攻击仍然存在,例如导致服务器分配非常大的 buffer,导致性能下降或内存耗尽崩溃。

为了使 Buffer 实例的创建更可靠且更不容易出错,各种形式的 new Buffer() 构造函数都已被弃用,且改为单独的 Buffer.from()Buffer.alloc()Buffer.allocUnsafe() 方法。

开发者应将 new Buffer() 构造函数的所有现有用法迁移到这些新的 API。

如果 size 小于或等于 Buffer.poolSize 的一半,则 Buffer.allocUnsafe()Buffer.from(array) 返回的 Buffer 实例可能是从共享的内部内存池中分配。 Buffer.allocUnsafeSlow() 返回的实例则从不使用共享的内部内存池。

--zero-fill-buffers 命令行选项#

中英对照

可以使用 --zero-fill-buffers 命令行选项启动 Node.js,以使所有新分配的 Buffer 实例在创建时默认使用零来填充。 如果没有该选项,则使用 Buffer.allocUnsafe()Buffer.allocUnsafeSlow()new SlowBuffer(size) 创建的 buffer 不会填充零。 使用这个选项可能会对性能产生重大的负面影响。 仅在需要强制新分配的 Buffer 实例不能包含可能敏感的旧数据时,才使用 --zero-fill-buffers 选项。

$ node --zero-fill-buffers
> Buffer.allocUnsafe(5);
<Buffer 00 00 00 00 00>

Buffer.allocUnsafe() 与 Buffer.allocUnsafeSlow() 不安全的原因#

中英对照

当调用 Buffer.allocUnsafe()Buffer.allocUnsafeSlow() 时,分配的内存片段是未初始化的(没有被清零)。 虽然这样的设计使得内存的分配非常快,但分配的内存可能包含敏感的旧数据。 使用由 Buffer.allocUnsafe() 创建的 Buffer 没有完全重写内存,当读取 Buffer 的内存时,可能使旧数据泄露。

虽然使用 Buffer.allocUnsafe() 有明显的性能优势,但必须格外小心,以避免将安全漏洞引入应用程序。