【Node】Node的Buffer模块介绍和使用

目录

简言

buffer 是指一个专门存放二进制数据的缓冲区。
Node中也实现了buffer的概念和操作方法,就是Buffer模块,也是node模块核心模块之一。
如果你js学的深的话,你会发现js也有一个内置对象ArrayBuffer和这个差不多,这里不展开描述。

Buffer模块

缓冲区(buffer)对象用于表示固定长度的字节序列(二进制数据)。许多 Node.js API 都支持缓冲区。
Buffer 类是 JavaScript 的 Uint8Array 类的子类,并用涵盖更多用例的方法对其进行了扩展。Node.js API 接受纯 Uint8Array,但也支持 Buffer。
虽然 Buffer 类在全局范围内可用,但仍建议通过导入或 require 语句显式地引用它。

import { Buffer } from "node:buffer";
//  创建长度为 10 的零填充缓冲区。
const buf1 = Buffer.alloc(10);
console.log(buf1);
//  创建长度为10,值都为1的缓冲区
const buf2 = Buffer.alloc(10, 1);
console.log(buf2);
//  快速创建长度为10的零缓冲区,不清除旧数据
const buf3 = Buffer.allocUnsafe(10);
console.log(buf3);
//  创建一个包含字节 [1, 2, 3] 的缓冲区。
const buf4 = Buffer.from([1, 2, 3]);
console.log(buf4);
//  创建一个缓冲区,其中包含 "test "字符串的 UTF-8 编码字节
const buf6 = Buffer.from("test");
console.log(buf6);

Buffer和字符编码

一碰到二进制数据(字节序列),就不可避免的接触字符编码;因为二进制我们看不懂,机器可以读懂,我们可以看懂字符,机器只认二进制;所以,字符编码就出现了,当然,字符编码类型有很多,不同的字符编码会造成乱码问题(就是我们看不懂,内容是不可理解的)。
在 Buffer 和字符串之间转换时,可以指定字符编码。如果没有指定字符编码,则默认使用 UTF-8。

import { Buffer } from 'node:buffer';

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

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

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

Node.js 缓冲区接受接收到的编码字符串的所有大小写变化。例如,UTF-8 可以指定为 “utf8”、"UTF8 "或 “uTf8”。

Node.js 目前支持以下字符编码:

  • ‘utf8’ —— 多字节编码的 Unicode 字符。许多网页和其他文档格式都使用 UTF-8。这是默认的字符编码。将缓冲区解码为不完全包含有效 UTF-8 数据的字符串时,将使用 Unicode 替代字符 U+FFFD � 来表示这些错误。
  • ‘utf16le’ —— 多字节编码的 Unicode 字符。与 "utf8 "不同,字符串中的每个字符将使用 2 或 4 个字节编码。Node.js 仅支持 UTF-16 的 little-endian 变体。
  • ‘latin1’ —— Latin-1 代表 ISO-8859-1。这种字符编码只支持从 U+0000 到 U+00FF 的 Unicode 字符。每个字符使用一个字节编码。不在该范围内的字符将被截断,并映射到该范围内的字符。

使用上述方法之一将缓冲区转换成字符串称为解码,将字符串转换成缓冲区称为编码。

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

  • ‘base64’ —— Base64 编码。从字符串创建缓冲区时,该编码也将正确接受 RFC 4648 第 5 节规定的 “URL 和文件名安全字母”。Base64 编码字符串中包含的空白字符(如空格、制表符和新行)将被忽略。
  • ‘base64url’ —— base64url 编码,如 RFC 4648 第 5 节所述。从字符串创建 Buffer 时,该编码也能正确接受普通的 base64 编码字符串。将 Buffer 编码为字符串时,该编码将省略填充。
  • ‘hex’ —— 将每个字节编码为两个十六进制字符。如果解码字符串不完全由偶数个十六进制字符组成,可能会出现数据截断现象。

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

  • ‘ascii’ —— 仅适用于 7 位 ASCII 数据。将字符串编码到 Buffer 时,相当于使用 “latin1”。在将 Buffer 解码为字符串时,使用该编码会在解码为 "latin1 "之前额外取消设置每个字节的最高位。一般来说,没有理由使用这种编码,因为在编码或解码纯 ASCII 文本时,“utf8”(或者,如果已知数据总是纯 ASCII,则使用 “latin1”)是更好的选择。提供这种编码只是为了与传统编码兼容。
  • ‘binary’ —— latin1 "的别名。这种编码的名称可能非常容易引起误解,因为这里列出的所有编码都可以在字符串和二进制数据之间进行转换。对于字符串和缓冲区之间的转换,"utf8 "通常是正确的选择。
  • ‘ucs2’, ‘ucs-2’ —— utf16le "的别名。UCS-2 曾经是指 UTF-16 的一种变体,它不支持码位大于 U+FFFF 的字符。在 Node.js 中,始终支持这些码位。
import { Buffer } from 'node:buffer';

Buffer.from('1ag123', 'hex');
// Prints <Buffer 1a>, data truncated when first non-hexadecimal value
// ('g') encountered.

Buffer.from('1a7', 'hex');
// Prints <Buffer 1a>, data truncated when data ends in single digit ('7').

Buffer.from('1634', 'hex');
// Prints <Buffer 16 34>, all data represented.

现代网络浏览器遵循 WHATWG 编码标准,该标准将 "latin1 "和 "ISO-8859-1 "别名为 “win-1252”。这就意味着,在执行类似 http.get() 的操作时,如果返回的字符集是 WHATWG 规范中列出的字符集之一,服务器就有可能实际返回了 "win-1252 "编码的数据,而使用 "latin1 "编码可能会错误地解码这些字符。

Buffer和 TypedArrays 缓冲区和类数组视图

TypedArray不是具体的一个类,它是指Uint8Array、Int16Array等类型化数组。
Buffer 实例也是 JavaScript Uint8Array 和 TypedArray 实例。所有 TypedArray 方法都可用于缓冲区。不过,Buffer API 和 TypedArray API 之间存在一些微妙的不兼容性。
例如:

  • TypedArray.prototype.slice() 会创建一个 TypedArray 部分的副本,而 Buffer.prototype.slice() 则会在现有 Buffer 上创建一个视图,但不会复制。这种行为可能会令人惊讶,它的存在只是为了实现传统的兼容性。TypedArray.prototype.subarray()可用于在Buffer和其他TypedArray上实现Buffer.prototype.slice()的行为,因此应优先使用TypedArray.prototype.subarray()。
  • buf.toString()与其对应的 TypedArray 不兼容。
  • 一些方法(如 buf.indexOf())支持附加参数。

从缓冲区创建新的 TypedArray 实例有两种方法:

  1. 将 Buffer 传递给 TypedArray 构造函数将复制 Buffer 的内容,并将其解释为整数数组,而不是目标类型的字节序列。
import { Buffer } from 'node:buffer';

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

console.log(uint32array);

// Prints: Uint32Array(4) [ 1, 2, 3, 4 ]
  1. 传递 Buffer 的底层 ArrayBuffer 将创建一个与 Buffer 共享内存的 TypedArray。
import { Buffer } from 'node:buffer';

const buf = Buffer.from('hello', 'utf16le');
const uint16array = new Uint16Array(
  buf.buffer,
  buf.byteOffset,
  buf.length / Uint16Array.BYTES_PER_ELEMENT);

console.log(uint16array);

// Prints: 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);
// Prints: <Buffer 88 a0>
console.log(buf2);
// Prints: <Buffer 88 13 a0 0f>

arr[1] = 6000;

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

使用 TypedArray 的 .buffer 创建缓冲区时,可以通过传递 byteOffset 和 length 参数,只使用底层 ArrayBuffer 的一部分。

import { Buffer } from 'node:buffer';

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

console.log(buf.length);
// Prints: 16

Buffer.from() 和 TypedArray.from() 有不同的签名和实现。具体来说,TypedArray 变体接受的第二个参数是一个映射函数,该函数会在类型化数组的每个元素上调用:

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

但是,Buffer.from() 方法不支持使用映射函数:

  • Buffer.from(array)
  • Buffer.from(buffer)
  • Buffer.from(arrayBuffer[, byteOffset[, length]])
  • Buffer.from(string[, encoding])

Buffers 和 iteration 缓冲区和迭代(遍历)

可以使用 for…of 语法遍历缓冲区实例:

import { Buffer } from 'node:buffer';

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

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

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

Class: Blob

Blob类在node:buffer模块中
Blob 封装了不可变的原始数据,可在多个工作线程之间安全共享。

new buffer.Blob([sources[, options]]) 创建blob实例

创建一个新的 Blob 对象,其中包含给定来源的连接。
参数:

  • sources —— 将存储在 Blob 中的字符串、<ArrayBuffer>、<TypedArray>、<DataView> 或 <Blob> 对象的数组,或这些对象的任意组合。啥意思呢?就是二进制数据。
  • options :选项
    • endings —— 行尾处理类型。 “transparent "或 "native"之一。设置为 "native"时,字符串源文件中的行尾将转换为 require(‘node:os’).EOL 指定的平台本地行尾。
    • type —— Blob 内容类型。类型的目的是传达数据的 MIME 媒体类型,但不对类型格式进行验证。

<ArrayBuffer>、<TypedArray>、<DataView> 和 <Buffer> 源会被复制到 "Blob "中,因此可以在创建 "Blob "后安全地进行修改。
字符串源被编码为 UTF-8 字节序列并复制到 Blob 中。每个字符串部分中不匹配的代理对将被 Unicode U+FFFD 替换字符替换。

blob.arrayBuffer() 转换成ArrayBuffer

返回一个包含 Blob 数据副本的 <ArrayBuffer> 的 promise。

blob.size 数据大小

Blob 的总大小(字节)。

blob.slice([start[, end[, type]]]) 新建一个子集blob

创建并返回一个新 Blob,其中包含该 Blob 对象数据的子集。原始 Blob 不会改变。

blob.stream() 流读取

返回一个新的 ReadableStream,允许读取 Blob 的内容。

blob.text() 转文本

返回一个以 UTF-8 字符串形式解码 Blob 内容的promise。

blob.type 类型

Blob 的内容类型。

import { Buffer, Blob } from "node:buffer";
const buf = Buffer.from([1, 2, 3]);
const blob = new Blob(buf);

console.log(blob, blob.size, blob.type);
blob.text().then((res) => {
  console.log("blob转文本", res);
});

blob对象和 MessageChannel

创建<Blob> 对象后,可以通过 MessagePort 将其发送到多个目的地,而无需传输或立即复制数据。Blob 中包含的数据只有在调用 arrayBuffer() 或 text() 方法时才会被复制。

import { Blob } from 'node:buffer';
import { setTimeout as delay } from 'node:timers/promises';

const blob = new Blob(['hello there']);

const mc1 = new MessageChannel();
const mc2 = new MessageChannel();

mc1.port1.onmessage = async ({ data }) => {
  console.log(await data.arrayBuffer());
  mc1.port1.close();
};

mc2.port1.onmessage = async ({ data }) => {
  await delay(1000);
  console.log(await data.arrayBuffer());
  mc2.port1.close();
};

mc1.port2.postMessage(blob);
mc2.port2.postMessage(blob);

// The Blob is still usable after posting.
blob.text().then(console.log);

Class: Buffer

缓冲区(Buffer)类是一种直接处理二进制数据的全局类型。它有多种构造方法。

Buffer.alloc(size[, fill[, encoding]]) 创建新buffer

静态方法。
参数:

  • size —— 新缓冲区的预期长度。
  • fill —— 预填充新缓冲区的值。默认值:0。
  • encoding —— 如果 fill 是字符串,这是它的编码。默认值:“utf8”。
    分配一个大小为字节的新 Buffer。如果 fill 未定义,Buffer 将被清零。
import { Buffer } from 'node:buffer';

const buf = Buffer.alloc(5);

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

如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,则抛出ERR_OUT_OF_RANGE。
如果指定了 fill,分配的缓冲区将通过调用 buf.fill(fill) 进行初始化。
如果同时指定了 fill 和编码,分配的 Buffer 将通过调用 buf.fill(fill, encoding) 进行初始化。

import { Buffer } from 'node:buffer';

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

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

调用 Buffer.alloc()可能会比 Buffer.allocUnsafe() 慢一些,但可以确保新创建的缓冲区实例内容绝不会包含以前分配的敏感数据,包括可能未分配给缓冲区的数据。

如果 size 不是数字,将产生 TypeError 错误。

Buffer.allocUnsafe(size) 快速创建新缓冲区

分配一个大小为字节的新缓冲区。如果大小大于 buffer.constants.MAX_LENGTH 或小于 0,将抛出 ERR_OUT_OF_RANGE。
以这种方式创建的缓冲区实例的底层内存未初始化。新创建的 Buffer 内容未知,可能包含敏感数据。请使用 Buffer.alloc() 以零初始化 Buffer 实例。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(10);

console.log(buf);
// Prints (contents may vary): <Buffer a0 8b 28 3f 01 00 00 00 50 32>

buf.fill(0);

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

Buffer 模块会预先分配一个大小为 Buffer.poolSize 的内部 Buffer 实例,仅当 Buffer.poolSize 小于 Buffer.poolSize >>> 1(Buffer.poolSize 的下限除以 2)时,才将其用作池,用于快速分配使用 Buffer.allocUnsafe()、Buffer.from(array) 和 Buffer.concat() 创建的新 Buffer 实例。
使用预分配的内部内存池是调用 Buffer.alloc(size, fill) 与 Buffer.allocUnsafe(size).fill(fill) 之间的主要区别。具体来说,Buffer.alloc(size, fill) 永远不会使用内部缓冲区内存池,而 Buffer.allocUnsafe(size).fill(fill) 会在大小小于或等于 Buffer.poolSize 的一半时使用内部缓冲区内存池。两者之间的区别很微妙,但当应用程序需要 Buffer.allocUnsafe() 提供的额外性能时,这种区别就显得尤为重要。

Buffer.allocUnsafeSlow(size) 创建缓冲区,保留内存

分配一个大小为字节的新缓冲区。如果 size 大于 buffer.constants.MAX_LENGTH 或小于 0,将抛出 ERR_OUT_OF_RANGE。如果 size 为 0,则会创建一个零长度的 Buffer。
以这种方式创建的缓冲区实例的底层内存未初始化。新创建的 Buffer 内容未知,可能包含敏感数据。请使用 buf.fill(0) 以零初始化此类 Buffer 实例。
在使用 Buffer.allocUnsafe() 分配新缓冲区实例时,4 KiB 以下的分配将从单个预分配缓冲区中切分。这样,应用程序就可以避免因创建多个单独分配的 Buffer 实例而产生的垃圾回收开销。这种方法无需跟踪和清理大量单独的 ArrayBuffer 对象,从而提高了性能和内存使用率。
不过,如果开发人员需要在一段不确定的时间内保留内存池中的一小块内存,那么使用 Buffer.allocUnsafeSlow() 创建一个未入池的缓冲区实例,然后复制出相关位可能是合适的。

import { Buffer } from 'node:buffer';

// Need to keep around a few small chunks of memory.
const store = [];

socket.on('readable', () => {
  let data;
  while (null !== (data = readable.read())) {
    // Allocate for retained data.
    const sb = Buffer.allocUnsafeSlow(10);

    // Copy the data into the new allocation.
    data.copy(sb, 0, 0, 10);

    store.push(sb);
  }
});

Buffer.byteLength(string[, encoding]) 获取数据字节长度

返回使用编码编码时字符串的字节长度。这与 String.prototype.length 不同,后者不考虑用于将字符串转换为字节的编码。
对于 “base64”、"base64url "和 “hex”,该函数假定输入有效。对于包含非 base64/hex 编码数据(如空白)的字符串,返回值可能大于根据字符串创建的 Buffer 的长度。

import { Buffer } from 'node:buffer';

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

console.log(`${str}: ${str.length} characters, ` +
            `${Buffer.byteLength(str, 'utf8')} bytes`);
// Prints: ½ + ¼ = ¾: 9 characters, 12 bytes

当字符串是 Buffer/DataView/TypedArray/ArrayBuffer/ SharedArrayBuffer 时,将返回 .byteLength 所报告的字节长度。

Buffer.compare(buf1, buf2) 缓冲区比较

比较 buf1 和 buf2,通常用于对 Buffer 实例数组进行排序。这相当于调用 buf1.compare(buf2)。

import { Buffer } from 'node:buffer';

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

console.log(arr.sort(Buffer.compare));
// Prints: [ <Buffer 30 31 32 33>, <Buffer 31 32 33 34> ]
// (This result is equal to: [buf2, buf1].)

Buffer.concat(list[, totalLength]) 合并缓冲区

返回一个新的缓冲区,它是将列表中所有缓冲区实例连接在一起的结果。
如果列表中没有项目,或者 totalLength 为 0,则返回一个新的零长度 Buffer。
如果未提供 totalLength,则将从列表中的缓冲区实例中通过加长计算得出。
如果提供了 totalLength,则会将其强制转换为无符号整数。如果列表中缓冲区的总长度超过 totalLength,结果将被截断为 totalLength。

import { Buffer } from "node:buffer";


const buf1 = Buffer.alloc(10, "1");
const buf2 = Buffer.alloc(14, "2");
const buf3 = Buffer.alloc(18, "3");
const totalLength = buf1.length + buf2.length + buf3.length;

console.log(totalLength);
// Prints: 42

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

console.log(bufA);
console.log(bufA.length);
// Prints: 47

Buffer.concat() 也可以像 Buffer.allocUnsafe() 一样使用内部缓冲池。

Buffer.copyBytesFrom(view[, offset[, length]]) 使用类型数组创建缓冲区

将视图的底层内存复制到新的 Buffer 中。
参数:

  • view <TypedArray> 要复制的 <TypedArray> 视图。
  • offset <整数> 视图内的起始偏移量。默认值:0。
  • length <整数> 要复制的视图中元素的个数。默认值:view.length - offset。
const u16 = new Uint16Array([0, 0xffff]);
const buf = Buffer.copyBytesFrom(u16, 1, 1);
u16[1] = 0;
console.log(buf.length); // 2
console.log(buf[0]); // 255
console.log(buf[1]); // 255 

Buffer.from(array) 数组创建缓冲区

使用范围在 0 - 255 之间的字节数组分配一个新缓冲区。超出该范围的数组条目将被截断以适应该范围。

import { Buffer } from 'node:buffer';

// Creates a new Buffer containing the UTF-8 bytes of the string 'buffer'.
const buf = Buffer.from([0x62, 0x75, 0x66, 0x66, 0x65, 0x72]);

如果数组是一个类似 Array 的对象(即具有数字类型 length 属性的对象),除非它是一个 Buffer 或 Uint8Array,否则会被当作数组处理。这意味着所有其他 TypedArray 变体都会被视为数组。要使用 Buffer.copyBytesFrom() 从支持类型数组的字节创建缓冲区,请使用 Buffer.copyBytesFrom()。
如果 array 不是数组或其他适合 Buffer.from() 变体的类型,则会出现 TypeError 错误。
Buffer.from(array) 和 Buffer.from(string) 也可以像 Buffer.allocUnsafe() 一样使用内部缓冲池。

Buffer.from(arrayBuffer[, byteOffset[, length]]) 使用arraybuffer创建缓冲区

这将创建 ArrayBuffer 的视图,而不会复制底层内存。例如,当传递 TypedArray 实例的 .buffer 属性引用时,新创建的缓冲区将与 TypedArray 的底层 ArrayBuffer 共享相同的分配内存。
可选的 byteOffset 和 length 参数指定了 Buffer 将共享的 arrayBuffer 中的内存范围。

import { Buffer } from 'node:buffer';

const arr = new Uint16Array(2);

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

// Shares memory with `arr`.
const buf = Buffer.from(arr.buffer);

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

// Changing the original Uint16Array changes the Buffer also.
arr[1] = 6000;

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

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

console.log(buf.length);
// Prints: 2

如果 arrayBuffer 不是 ArrayBuffer 或 SharedArrayBuffer 或其他适合 Buffer.from() 变体的类型,则会抛出 TypeError。
重要的是要记住,后备 ArrayBuffer 可覆盖的内存范围超出了 TypedArray 视图的边界。使用类型化数组的缓冲区属性创建的新缓冲区可能会超出类型化数组的范围:

import { Buffer } from 'node:buffer';

const arrA = Uint8Array.from([0x63, 0x64, 0x65, 0x66]); // 4 elements
const arrB = new Uint8Array(arrA.buffer, 1, 2); // 2 elements
console.log(arrA.buffer === arrB.buffer); // true

const buf = Buffer.from(arrB.buffer);
console.log(buf);
// Prints: <Buffer 63 64 65 66>

Buffer.from(buffer) 赋值缓冲区

将传递的缓冲区数据复制到一个新的缓冲区实例上。

import { Buffer } from 'node:buffer';

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

buf1[0] = 0x61;

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

如果 buffer 不是 Buffer 或其他适合 Buffer.from() 变体的类型,则会抛出 TypeError。

Buffer.from(object[, offsetOrEncoding[, length]]) 使用对象创建缓冲区

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

import { Buffer } from 'node:buffer';

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

对于支持 Symbol.toPrimitive 的对象,返回 Buffer.from(objectSymbol.toPrimitive, offsetOrEncoding)。

import { Buffer } from 'node:buffer';

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

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

如果对象不具备上述方法或不属于适合 Buffer.from() 变体的其他类型,则会抛出 TypeError。

Buffer.from(string[, encoding]) 字符串创建缓冲区

创建一个包含字符串的新缓冲区。编码参数用于确定将字符串转换为字节时使用的字符编码。

import { Buffer } from 'node:buffer';

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

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

如果 string 不是字符串或其他适合 Buffer.from() 变体的类型,则会抛出 TypeError。

Buffer.isBuffer(obj) 是否是buffer

如果 obj 是缓冲区,则返回 true,否则返回 false。

import { Buffer } from 'node:buffer';

Buffer.isBuffer(Buffer.alloc(10)); // true
Buffer.isBuffer(Buffer.from('foo')); // true
Buffer.isBuffer('a string'); // false
Buffer.isBuffer([]); // false
Buffer.isBuffer(new Uint8Array(1024)); // false

Buffer.isEncoding(encoding) 是否支持该编码格式

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

import { Buffer } from 'node:buffer';

console.log(Buffer.isEncoding('utf8'));
// Prints: true

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

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

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

Buffer.poolSize 预分配池大小

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

buf[index] buffer数据动态索引

索引操作符 [index] 可用于获取和设置位于 buf 中索引位置的八位字节。这些值指的是单个字节,因此合法取值范围是 0x00 至 0xFF(十六进制)或 0 至 255(十进制)。
该操作符继承自 Uint8Array,因此其越界访问行为与 Uint8Array 相同。换句话说,当 index 为负值或大于等于 buf.length 时,buf[index] 返回未定义值;而当 index 为负值或 >= buf.length 时,buf[index] = value 不会修改缓冲区。

import { Buffer } from 'node:buffer';

// Copy an ASCII string into a `Buffer` one byte at a time.
// (This only works for ASCII-only strings. In general, one should use
// `Buffer.from()` to perform this conversion.)

const str = 'Node.js';
const buf = Buffer.allocUnsafe(str.length);

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

console.log(buf.toString('utf8'));
// Prints: Node.js

buf.buffer 获取创建缓存区底层 ArrayBuffer 对象

创建 Buffer 对象所基于的底层 ArrayBuffer 对象。
不保证 ArrayBuffer 与原始 Buffer 完全一致。详情请参见 buf.byteOffset 的注释。

import { Buffer } from 'node:buffer';

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

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

buf.byteOffset buffer底层字节偏移

Buffers 底层 ArrayBuffer 对象的 byteOffset。
在 Buffer.from(ArrayBuffer, byteOffset, length) 中设置 byteOffset 时,或者有时在分配小于 Buffer.poolSize 的 Buffer 时,缓冲区不会从底层 ArrayBuffer 的零偏移开始。
这可能会在使用 buf.buffer 直接访问底层 ArrayBuffer 时造成问题,因为 ArrayBuffer 的其他部分可能与 Buffer 对象本身无关。
在创建与缓冲区共享内存的类型数组对象时,一个常见的问题是在这种情况下需要正确指定 byteOffset:

const nodeBuffer = Buffer.from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]);
//  将 Node.js 缓冲区转换为 Int8Array 时,使用byteOffset只引用' nodeBuffer '的一部分。包含' nodeBuffer '的内存。
const aa = new Int8Array(
  nodeBuffer.buffer,
  nodeBuffer.byteOffset,
  nodeBuffer.length
);

buf.compare(target[, targetStart[, targetEnd[, sourceStart[, sourceEnd]]]]) buffers比较

比较 buf 和 target,并返回一个数字,表示在排序顺序上,buf 是在 target 之前、之后还是相同。比较基于每个缓冲区中字节的实际顺序。
参数:

  • target —— 与 buf 比较的缓冲区或 Uint8Array。
  • targetStart <整数> —— 目标中开始比较的偏移量。默认值:0。
  • targetEnd <整数> —— 比较结束时目标内的偏移量(不包括在内)。默认值:target.length。
  • sourceStart <整数> —— 开始比较的 buf 中的偏移量。默认值:0。
  • sourceEnd <整数>—— 终止比较的 buf 中的偏移量(不包括在内)。默认值:buf.length。

返回值整数:

  • 如果 target 与 buf 相同,则返回 0
  • 如果排序时目标应在 buf 之前,则返回 1。
  • 如果排序时目标应在 buf 之后,则返回-1。
import { Buffer } from 'node:buffer';

const buf1 = Buffer.from('ABC');
const buf2 = Buffer.from('BCD');
const buf3 = Buffer.from('ABCD');

console.log(buf1.compare(buf1));
// Prints: 0
console.log(buf1.compare(buf2));
// Prints: -1
console.log(buf1.compare(buf3));
// Prints: -1
console.log(buf2.compare(buf1));
// Prints: 1
console.log(buf2.compare(buf3));
// Prints: 1
console.log([buf1, buf2, buf3].sort(Buffer.compare));
// Prints: [ <Buffer 41 42 43>, <Buffer 41 42 43 44>, <Buffer 42 43 44> ]
// (This result is equal to: [buf1, buf3, buf2].)

可选的 targetStart、targetEnd、sourceStart 和 sourceEnd 参数可用于将比较范围分别限制在 target 和 buf 中的特定范围内。

import { Buffer } from 'node:buffer';

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));
// Prints: 0
console.log(buf1.compare(buf2, 0, 6, 4));
// Prints: -1
console.log(buf1.compare(buf2, 5, 6, 5));
// Prints: 1

如果 targetStart < 0、sourceStart < 0、targetEnd > target.byteLength,或 sourceEnd > source.byteLength,则抛出ERR_OUT_OF_RANGE。

buf.copy(target[, targetStart[, sourceStart[, sourceEnd]]]) 复制缓冲区

将数据从 buf 中的一个区域复制到 target 中的一个区域,即使目标内存区域与 buf 重叠。
TypedArray.prototype.set() 执行相同的操作,适用于包括 Node.js 缓冲区在内的所有 TypedArray,尽管它使用不同的函数参数。

import { Buffer } from 'node:buffer';

// Create two `Buffer` instances.
const buf1 = Buffer.allocUnsafe(26);
const buf2 = Buffer.allocUnsafe(26).fill('!');

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'.
  buf1[i] = i + 97;
}

// Copy `buf1` bytes 16 through 19 into `buf2` starting at byte 8 of `buf2`.
buf1.copy(buf2, 8, 16, 20);
// This is equivalent to:
// buf2.set(buf1.subarray(16, 20), 8);

console.log(buf2.toString('ascii', 0, 25));
// Prints: !!!!!!!!qrst!!!!!!!!!!!!!
import { Buffer } from 'node:buffer';

// Create a `Buffer` and copy data from one region to an overlapping region
// within the same `Buffer`.

const buf = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'.
  buf[i] = i + 97;
}

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

console.log(buf.toString());
// Prints: efghijghijklmnopqrstuvwxyz

buf.entries() 返回 项为[index,byte]的迭代器

根据 buf 的内容创建并返回由 [index, byte] 对组成的迭代器。

import { Buffer } from 'node:buffer';

// Log the entire contents of a `Buffer`.

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

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

buf.equals(otherBuffer) 两buffer是否相等

如果 buf 和 otherBuffer 的字节完全相同,则返回 true,否则返回 false。等价于 buf.compare(otherBuffer) === 0。

import { Buffer } from 'node:buffer';

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

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

buf.fill(value[, offset[, end]][, encoding]) buffer填充数据

用指定值填充 buf。如果没有给出偏移量和结束值,将填充整个 buf:

import { Buffer } from 'node:buffer';

// Fill a `Buffer` with the ASCII character 'h'.

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

console.log(b.toString());
// Prints: hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh

// Fill a buffer with empty string
const c = Buffer.allocUnsafe(5).fill('');

console.log(c.fill(''));
// Prints: <Buffer 00 00 00 00 00>

如果 value 不是字符串、Buffer 或整数,就会被强制转换为 uint32 值。如果生成的整数大于 255(十进制),则会用值 & 255 填充 buf。
如果 fill() 操作的最后一次写入落在一个多字节字符上,则只写入该字符中适合写入 buf 的字节:

import { Buffer } from 'node:buffer';

// Fill a `Buffer` with character that takes up two bytes in UTF-8.

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

如果值包含无效字符,则会被截断;如果没有有效的填充数据,则会出现异常:

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(5);

console.log(buf.fill('a'));
// Prints: <Buffer 61 61 61 61 61>
console.log(buf.fill('aazz', 'hex'));
// Prints: <Buffer aa aa aa aa aa>
console.log(buf.fill('zz', 'hex'));
// Throws an exception.

buf.includes(value[, byteOffset][, encoding]) 是否包含具体值

等同于 buf.indexOf() !== -1。

import { Buffer } from 'node:buffer';

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

console.log(buf.includes('this'));
// Prints: true
console.log(buf.includes('is'));
// Prints: true
console.log(buf.includes(Buffer.from('a buffer')));
// Prints: true
console.log(buf.includes(97));
// Prints: true (97 is the decimal ASCII value for 'a')
console.log(buf.includes(Buffer.from('a buffer example')));
// Prints: false
console.log(buf.includes(Buffer.from('a buffer example').slice(0, 8)));
// Prints: true
console.log(buf.includes('this', 4));
// Prints: false

buf.indexOf(value[, byteOffset][, encoding]) 查找值返索引

如果值为

  • 字符串,值将根据 encoding 中的字符编码解释。
  • 缓冲区或 Uint8Array,将使用整个值。要比较部分 Buffer,请使用 buf.subarray。
  • 数字,值将被解释为介于 0 和 255 之间的无符号 8 位整数。
import { Buffer } from 'node:buffer';

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

console.log(buf.indexOf('this'));
// Prints: 0
console.log(buf.indexOf('is'));
// Prints: 2
console.log(buf.indexOf(Buffer.from('a buffer')));
// Prints: 8
console.log(buf.indexOf(97));
// Prints: 8 (97 is the decimal ASCII value for 'a')
console.log(buf.indexOf(Buffer.from('a buffer example')));
// Prints: -1
console.log(buf.indexOf(Buffer.from('a buffer example').slice(0, 8)));
// Prints: 8

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

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

如果 value 不是字符串、数字或缓冲区,本方法将引发 TypeError。如果 value 是数字,它将被强制转换为有效的字节值,即 0 到 255 之间的整数。
如果 byteOffset 不是数字,它将被强制转换为数字。如果强制的结果是 NaN 或 0,那么将搜索整个缓冲区。此行为与 String.prototype.indexOf() 匹配。

import { Buffer } from 'node:buffer';

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

// Passing a value that's a number, but not a valid byte.
// Prints: 2, equivalent to searching for 99 or 'c'.
console.log(b.indexOf(99.9));
console.log(b.indexOf(256 + 99));

// Passing a byteOffset that coerces to NaN or 0.
// Prints: 1, searching the whole 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 键(索引)的迭代器。

import { Buffer } from 'node:buffer';

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

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

buf.lastIndexOf(value[, byteOffset][, encoding]) 查找值最后一次出现位置

与 buf.indexOf() 相同,不同之处在于查找值的最后一次出现而不是第一次出现。

import { Buffer } from 'node:buffer';

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

console.log(buf.lastIndexOf('this'));
// Prints: 0
console.log(buf.lastIndexOf('buffer'));
// Prints: 17
console.log(buf.lastIndexOf(Buffer.from('buffer')));
// Prints: 17
console.log(buf.lastIndexOf(97));
// Prints: 15 (97 is the decimal ASCII value for 'a')
console.log(buf.lastIndexOf(Buffer.from('yolo')));
// Prints: -1
console.log(buf.lastIndexOf('buffer', 5));
// Prints: 5
console.log(buf.lastIndexOf('buffer', 4));
// Prints: -1

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

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

buf.length buffer字节数

返回 buf 中的字节数。

import { Buffer } from 'node:buffer';

// Create a `Buffer` and write a shorter string to it using UTF-8.

const buf = Buffer.alloc(1234);

console.log(buf.length);
// Prints: 1234

buf.write('some string', 0, 'utf8');

console.log(buf.length);
// Prints: 1234

buf.readBigInt64BE([offset]) 有符号、大端法读取值

参数:

  • offser —— 开始读取前要跳过的字节数。必须满足 0 <= 偏移量 <= buf.length - 8。默认值:0。

64位的 偏移量范围都是 0 <= offset <= buf.length - 8

在指定偏移量处从 buf 中读取一个带符号的大二进制 64 位整数。
从缓冲器读取的整数被解释为二进制符号值。

不同的计算机结构有时使用不同的字节顺序存储数据。
Big-Endian : 最重要的字节在整个内容的左端 ,大端法。
Little-Endian : 最重要的字节在整个内容的右端 , 小端法。

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

console.log(nodeBuffer.readBigInt64BE());
console.log(nodeBuffer.readBigInt64LE());

buf.readBigInt64LE([offset]) 有符号、小端法读取值

从指定偏移量处的 buf 读取带符号、小二进制的 64 位整数。
从缓冲区读取的整数被解释为二进制符号值。

buf.readBigUInt64BE([offset]) 无符号大端法读取值

在指定偏移量处从 buf 读取一个无符号、大二进制 64 位整数。
该函数也可以通过 readBigUint64BE 别名使用。

import { Buffer } from 'node:buffer';

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

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

buf.readBigUInt64LE([offset]) 无符号小端法读取值

在指定偏移量处从 buf 中读取一个无符号、小二进制的 64 位整数。
该函数也可以通过 readBigUint64LE 别名使用。

import { Buffer } from 'node:buffer';

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

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

buf.readDoubleBE([offset]) 双精度浮点数大端法读取值

从指定偏移量处的 buf 中读取一个 64 位大二进制二进制数。

import { Buffer } from 'node:buffer';

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

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

buf.readDoubleLE([offset]) 双精度浮点数小端法读取值

从指定偏移量处的 buf 读取一个 64 位小端双倍值。

import { Buffer } from 'node:buffer';

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

console.log(buf.readDoubleLE(0));
// Prints: 5.447603722011605e-270
console.log(buf.readDoubleLE(1));
// Throws ERR_OUT_OF_RANGE.

buf.readFloatBE([offset]) 单精度大端法读取值

从指定偏移量处的 buf 读取 32 位大整数浮点数。

32 位的 偏移量范围都是 0 <= offset <= buf.length - 4

import { Buffer } from 'node:buffer';

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

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

buf.readFloatLE([offset]) 单精度小端法读取值

从指定偏移量处的 buf 读取 32 位小端浮点数。

import { Buffer } from 'node:buffer';

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

console.log(buf.readFloatLE(0));
// Prints: 1.539989614439558e-36
console.log(buf.readFloatLE(1));
// Throws ERR_OUT_OF_RANGE.

buf.readInt8([offset])

参数:offset <整数> 开始读取前要跳过的字节数。必须满足 0 <= offset <= buf.length - 1。 默认值:0。
从指定偏移量处的 buf 读取一个带符号的 8 位整数。
从缓冲区读取的整数被解释为二进制符号值。

import { Buffer } from 'node:buffer';

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

console.log(buf.readInt8(0));
// Prints: -1
console.log(buf.readInt8(1));
// Prints: 5
console.log(buf.readInt8(2));
// Throws ERR_OUT_OF_RANGE.

buf.readInt16BE([offset]) 大端法读取16位整数值

参数:offset <整数> 开始读取前要跳过的字节数。必须满足 0 <= offset <= buf.length - 2。 默认值:0。
从指定偏移量处的 buf 读取带符号、大二进制的 16 位整数。
从缓冲器读取的整数被解释为二进制符号值。

import { Buffer } from 'node:buffer';

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

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

buf.readInt16LE([offset]) 小端法读取16位整数值

从指定偏移量处的 buf 读取带符号、小二进制的 16 位整数。
从缓冲器读取的整数被解释为二进制符号值。

import { Buffer } from 'node:buffer';

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

console.log(buf.readInt16LE(0));
// Prints: 1280
console.log(buf.readInt16LE(1));
// Throws ERR_OUT_OF_RANGE.

buf.readInt32BE([offset]) 大端法读取32位整数值

参数:offset — 开始读取前要跳过的字节数。必须满足 0 <= 偏移量 <= buf.length - 4。默认值:0。
从指定偏移量处的 buf 读取带符号的大三位 32 位整数。
从缓冲器读取的整数被解释为二进制符号值。

import { Buffer } from 'node:buffer';

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

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

buf.readInt32LE([offset]) 小端法读取32位整数值

从指定偏移量处的 buf 中读取带符号的 32 位小端整数。
从缓冲器读取的整数被解释为二进制符号值。

import { Buffer } from 'node:buffer';

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

console.log(buf.readInt32LE(0));
// Prints: 83886080
console.log(buf.readInt32LE(1));
// Throws ERR_OUT_OF_RANGE.

buf.readIntBE(offset, byteLength) 大端法读取整数类形值

从指定偏移量处的 buf 读取字节长度(byteLength)的字节数,并将结果解释为大二进制、二进制有符号数值,最高支持 48 位精度。
参数:

  • offset <整数> 开始读取前要跳过的字节数。必须满足 0 <= offset <= buf.length - byteLength。
  • byteLength <整数> 要读取的字节数。必须满足 0 <= byteLength <= 6。
import { Buffer } from 'node:buffer';

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

console.log(buf.readIntBE(0, 6).toString(16));
// Prints: 1234567890ab
console.log(buf.readIntBE(1, 6).toString(16));
// Throws ERR_OUT_OF_RANGE.
console.log(buf.readIntBE(1, 0).toString(16));
// Throws ERR_OUT_OF_RANGE.

buf.readIntLE(offset, byteLength)

从指定偏移量处的 buf 中读取字节长度(byteLength)的字节数,并将结果解释为小数点后两位、二进制有符号数值,最多支持 48 位精度。

import { Buffer } from 'node:buffer';

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

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

buf.readUInt8([offset]) 读取无符号的8位整数

从指定偏移量处的 buf 读取一个无符号 8 位整数。

buf.readUInt16BE([offset]) 大端法读取无符号的16位整数

从指定偏移量处的 buf 读取一个无符号、大二进制的 16 位整数。

buf.readUInt16LE([offset]) 小端法读取无符号的16位整数

在指定偏移量处从 buf 中读取一个无符号、小二进制 16 位整数。

buf.readUInt32BE([offset]) 大端法读取无符号的32位整数

从指定偏移量处的 buf 读取一个无符号、大二进制的 32 位整数。
该函数的别名为 readUint32BE。

buf.readUInt32LE([offset]) 小端法读取无符号的32位整数

在指定偏移量处从 buf 中读取一个无符号、小二进制的 32 位整数。
该函数的别名为 readUint32LE。

buf.readUIntBE(offset, byteLength) 大端法读取无符号的整数

从指定偏移量处的 buf 读取字节长度(byteLength)的字节数,并将结果解释为无符号大端整数,最高支持 48 位精度。
该函数也可在 readUintBE 别名下使用。

buf.readUIntLE(offset, byteLength) 小端法读取无符号的整数

从指定偏移量处的 buf 读取字节长度(byteLength)的字节数,并将结果解释为无符号、小双序整数,最多支持 48 位精度。
该函数也可在 readUintLE 别名下使用。

buf.subarray([start[, end]]) 截取buffer

返回一个新的缓冲区,该缓冲区引用了与原始缓冲区相同的内存,但根据开始和结束索引进行了偏移和裁剪。
指定 end 大于 buf.length 将返回与 end 等于 buf.length 相同的结果。
该方法继承自 TypedArray.prototype.subarray()。
修改新的缓冲区片段将修改原始缓冲区中的内存,因为两个对象的分配内存是重叠的。

import { Buffer } from 'node:buffer';

// Create a `Buffer` with the ASCII alphabet, take a slice, and modify one byte
// from the original `Buffer`.

const buf1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'.
  buf1[i] = i + 97;
}

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

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

buf1[0] = 33;

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

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

import { Buffer } from 'node:buffer';

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

console.log(buf.subarray(-6, -1).toString());
// Prints: buffe
// (Equivalent to buf.subarray(0, 5).)

console.log(buf.subarray(-6, -2).toString());
// Prints: buff
// (Equivalent to buf.subarray(0, 4).)

console.log(buf.subarray(-5, -2).toString());
// Prints: uff
// (Equivalent to buf.subarray(1, 4).)

buf.swap16() 16位转换字节顺序

将 buf 解释为无符号 16 位整数数组,并就地交换字节顺序。如果 buf.length 不是 2 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE。

import { Buffer } from 'node:buffer';

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

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

buf1.swap16();

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

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

buf2.swap16();
// Throws ERR_INVALID_BUFFER_SIZE.

buf.swap16() 的一个方便用途是在 UTF-16 little-endian 和 UTF-16 big-endian 之间进行快速就地转换:

import { Buffer } from 'node:buffer';

const buf = Buffer.from('This is little-endian UTF-16', 'utf16le');
buf.swap16(); // Convert to big-endian UTF-16 text.

buf.swap32() 32位转换字节顺序

将 buf 解释为无符号 32 位整数数组,并就地交换字节顺序。如果 buf.length 不是 4 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE。

import { Buffer } from 'node:buffer';

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

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

buf1.swap32();

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

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

buf2.swap32();
// Throws ERR_INVALID_BUFFER_SIZE.

buf.swap64() 64位转换字节顺序

将 buf 解释为一个 64 位数字数组,并就地交换字节顺序。如果 buf.length 不是 8 的倍数,则抛出 ERR_INVALID_BUFFER_SIZE。

import { Buffer } from 'node:buffer';

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

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

buf1.swap64();

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

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

buf2.swap64();
// Throws ERR_INVALID_BUFFER_SIZE.

buf.toJSON() 获取JSON

返回 buf 的 JSON 表示形式。在对 Buffer 实例进行字符串化时,JSON.stringify() 会隐式调用此函数。
Buffer.from() 接受该方法返回的格式的对象。特别是,Buffer.from(buf.toJSON()) 的工作方式与 Buffer.from(buf) 类似。

import { Buffer } from 'node:buffer';

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

console.log(json);
// Prints: {"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);
// Prints: <Buffer 01 02 03 04 05>

buf.toString([encoding[, start[, end]]]) 获取指定编码的字符串

根据 encoding 中指定的字符编码将 buf 解码为字符串。
如果编码为 “utf8”,而输入中的字节序列不是有效的 UTF-8,那么每个无效字节都会被替换为替换字符 U+FFFD。
字符串实例的最大长度(以 UTF-16 编码单位表示)作为 buffer.constants.MAX_STRING_LENGTH 提供。

import { Buffer } from 'node:buffer';

const buf1 = Buffer.allocUnsafe(26);

for (let i = 0; i < 26; i++) {
  // 97 is the decimal ASCII value for 'a'.
  buf1[i] = i + 97;
}

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

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

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

buf.values() 获取值的迭代器

创建并返回 buf 值(字节)的迭代器。在 for…of 语句中使用缓冲区时,该函数将被自动调用。

import { Buffer } from 'node:buffer';

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

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

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

buf.write(string[, offset[, length]][, encoding]) 字符写入缓冲区

根据 encoding 中的字符编码,将字符串写入偏移量处的 buf。长度参数是要写入的字节数。如果 buf 中没有足够的空间容纳整个字符串,则只会写入字符串的一部分。但是,部分编码字符不会被写入。
参数:

  • string <string> 要写入 buf 的字符串。
  • offset <整数> 开始写入字符串前要跳过的字节数。默认值:0。
  • length <整数> 要写入的最大字节数(写入的字节数不会超过 buf.length - 偏移量)。默认:buf.length - 偏移量。
  • encoding <string> 字符串的字符编码。默认:‘utf8’。

返回值是写入的字节数。

import { Buffer } from 'node:buffer';

const buf = Buffer.alloc(256);

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

console.log(`${len} bytes: ${buf.toString('utf8', 0, len)}`);
// Prints: 12 bytes: ½ + ¼ = ¾

const buffer = Buffer.alloc(10);

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

console.log(`${length} bytes: ${buffer.toString('utf8', 8, 10)}`);
// Prints: 2 bytes : ab

buf.writeBigInt64BE(value[, offset]) 大端法写入bigInt类型值

参数:

  • value <bigint>要写入 buf 的数字。
  • offset <整数> 开始写入前要跳过的字节数。必须满足0 <= offset <= buf.length - 8。默认值:0。
    将指定偏移量处的值以 big-endian 格式写入 buf。
    value参数被解释并写成一个二进制带符号整数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigInt64BE(0x0102030405060708n, 0);

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

buf.writeBigInt64LE(value[, offset]) 小端法写入bigInt类型值

以 little-endian 方式将值写入指定偏移量处的 buf。

buf.writeBigUInt64BE(value[, offset]) 大端法写入无符号bigInt类型值

将指定偏移量处的值以 big-endian 格式写入 buf。
该函数也可在 writeBigUint64BE 别名下使用。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeBigUInt64BE(0xdecafafecacefaden, 0);

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

buf.writeBigUInt64LE(value[, offset]) 小端法写入无符号bigInt类型值

将指定偏移量处的值以 little-endian 格式写入 buf

buf.writeDoubleBE(value[, offset]) 大端法写入double类型值

参数:

  • value <数字> 要写入 buf 的数字。
  • offset <整数> 开始写入前要跳过的字节数。必须满足 0 <= offset <= buf.length - 8。默认值:0。

在指定偏移量处以 big-endian 方式将值写入 buf。值必须是 JavaScript 数字。如果值不是 JavaScript 数字,则行为未定义。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(8);

buf.writeDoubleBE(123.456, 0);

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

buf.writeDoubleLE(value[, offset]) 小端法写入double类型值

将值以 little-endian 格式写入指定偏移量处的 buf。值必须是 JavaScript 数字。如果值不是 JavaScript 数字,则行为未定义。

buf.writeFloatBE(value[, offset]) 大端法写入float类型值

参数:

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

在指定偏移量处以 big-endian 方式将值写入 buf。当值不是 JavaScript 数字时,行为未定义。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeFloatBE(0xcafebabe, 0);

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

buf.writeFloatLE(value[, offset]) 小端法写入float类型值

将值以 little-endian 格式写入指定偏移量处的 buf。当值不是 JavaScript 数字时,行为未定义。

buf.writeInt8(value[, offset]) 写入8位整数值

参数:

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

将值写入指定偏移量处的 buf。值必须是有效的带符号 8 位整数。如果值不是带符号的 8 位整数,则行为未定义。
值被解释并写成一个二进制带符号整数。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(2);

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

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

buf.writeInt16BE(value[, offset]) 大端法写入16位整数值

参数:

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

在指定偏移量处以 big-endian 方式向 buf 写入数值。值必须是有效的带符号 16 位整数。如果值不是带符号的 16 位整数,则行为未定义。
该值被解释并写为一个二进制带符号整数。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(2);

buf.writeInt16BE(0x0102, 0);

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

buf.writeInt16LE(value[, offset]) 小端法写入16位整数值

将值以 little-endian 方式写入指定偏移量处的 buf。值必须是有效的带符号 16 位整数。如果值不是带符号的 16 位整数,则行为未定义。
该值被解释并写为一个二进制带符号整数。

buf.writeInt32BE(value[, offset]) 大端法写入32位整数值

参数:

  • value <整数> 要写入 buf 的数字。
  • offset <整数> 开始写入前要跳过的字节数。必须满足 0 <= offset <= buf.length - 4。默认值:0。
    在指定偏移量处向 buf 以 big-endian 方式写入数值。值必须是有效的带符号 32 位整数。如果值不是带符号的 32 位整数,则行为未定义。
    该值被解释并写为一个二进制带符号整数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeInt32BE(0x01020304, 0);

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

buf.writeInt32LE(value[, offset]) 小端法写入32位整数值

以 little-endian 方式将值写入指定偏移量处的 buf。值必须是有效的带符号 32 位整数。如果值不是带符号的 32 位整数,则行为未定义。

buf.writeIntBE(value, offset, byteLength) 大端法写入指定字节数整数值

参数:

  • value <整数> 要写入 buf 的数字。
  • offset <整数> 开始写入前要跳过的字节数。必须满足 0 <= offset <= buf.length - byteLength。
  • byteLength <整数> 要写入的字节数。必须满足 0 <= byteLength <= 6。

在指定偏移量处以 big-endian 方式向 buf 写入 byteLength 字节的值。最多支持 48 位精度。如果值不是带符号整数,则行为未定义。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

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

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

buf.writeIntLE(value, offset, byteLength) 小端法写入指定字节数整数值

在指定偏移量处以 little-endian 方式向 buf 写入 byteLength 字节的值。最多支持 48 位精度。如果值不是带符号整数,则行为未定义。

buf.writeUInt8(value[, offset]) 写入无符号8位整数

将值写入指定偏移量处的 buf。值必须是有效的无符号 8 位整数。如果值不是无符号 8 位整数,则行为未定义。
该函数也可在 writeUint8 别名下使用。
参数:

  • value —— 要写入 buf 的数字。
  • offset —— 开始写入前要跳过的字节数。必须满足 0 <= 偏移量 <= buf.length - 1。 默认值:0。
  • 返回值 —— 偏移量加上写入的字节数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

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

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

buf.writeUInt16BE(value[, offset])大端法写入无符号16位整数

在指定偏移量处向 buf 写入大端位数值。值必须是有效的无符号 16 位整数。如果值不是无符号 16 位整数,则行为未定义。
该函数也可在 writeUint16BE 别名下使用。
参数:

  • value —— 要写入 buf 的数字。
  • offset —— 开始写入前要跳过的字节数。必须满足 0 <= 偏移量 <= buf.length - 2。 默认值:0。
  • 返回值 —— 偏移量加上写入的字节数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

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

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

buf.writeUInt16LE(value[, offset]) 小端法写入无符号16位整数

将值以 little-endian 方式写入指定偏移量处的 buf。值必须是有效的无符号 16 位整数。如果值不是无符号 16 位整数,则行为未定义。
该函数也可在 writeUint16LE 别名下使用。

buf.writeUInt32BE(value[, offset])大端法写入无符号32位整数

在指定偏移量处向 buf 以 big-endian 方式写入数值。值必须是有效的无符号 32 位整数。如果值不是无符号 32 位整数,则行为未定义。
该函数也可在 writeUint32BE 别名下使用。
参数:

  • value —— 要写入 buf 的数字。
  • offset —— 开始写入前要跳过的字节数。必须满足 0 <= 偏移量 <= buf.length - 4。 默认值:0。
  • 返回值 —— 偏移量加上写入的字节数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32BE(0xfeedface, 0);

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

buf.writeUInt32LE(value[, offset])小端法写入无符号32位整数

将值以 little-endian 方式写入指定偏移量处的 buf。值必须是有效的无符号 32 位整数。如果值不是无符号 32 位整数,则行为未定义。
该函数也可在 writeUint32LE 别名下使用。

import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(4);

buf.writeUInt32LE(0xfeedface, 0);

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

buf.writeUIntBE(value, offset, byteLength) 大端法写入无符号整数

在指定偏移量处以 big-endian 方式向 buf 写入 byteLength 字节的值。最多支持 48 位精度。如果值不是无符号整数,则行为未定义。
该函数也可在 writeUintBE 别名下使用。
参数:

  • value <整数> 要写入 buf 的数字。
  • offset <整数> 开始写入前要跳过的字节数。必须满足 0 <= offset <= buf.length - byteLength。
  • byteLength <整数> 要写入的字节数。必须满足 0 <= byteLength <= 6。
  • 返回值: 偏移量加上写入的字节数。
import { Buffer } from 'node:buffer';

const buf = Buffer.allocUnsafe(6);

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

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

buf.writeUIntLE(value, offset, byteLength) 小端法写入无符号整数

在指定偏移量处以 little-endian 方式向 buf 写入 byteLength 字节的值。最多支持 48 位精度。如果值不是无符号整数,则行为未定义。
该函数也可在 writeUintLE 别名下使用。

Class: File 文件类

文件提供有关文件的信息。

new buffer.File(sources, fileName[, options]) 将数据存到文件中

参数:

  • sources —— 字符串、<ArrayBuffer>、<TypedArray>、<DataView>、<File> 或 <Blob> 对象的数组,或这些对象的任意组合,这些对象将存储在文件中。
  • filename —— 文件名。
  • oprions —— 配置对象
    • endings ——“ transparent"或 "native"之一。设置为 "native"时,字符串源文件中的行结束符将转换为 require(‘node:os’).EOL 指定的平台本地行结束符。
    • type —— 文件类型。
    • lastModified —— 文件的最后修改日期。默认值:Date.now()。

file.name 文件名称。

文件名称。

file.lastModified 文件最后修改日期

文件的最后修改日期。

node:buffer 模块 API

虽然 Buffer 对象是全局对象,但还有其他与 Buffer 相关的 API,这些 API 只能通过使用 require(‘node:buffer’) 访问 node:buffer 模块来获得。

buffer.atob(data) 解码base64编码的数据

将 Base64 编码的数据字符串解码为字节,并使用 Latin-1 (ISO-8859-1) 将这些字节编码为字符串。
数据可以是任何可以强制转换成字符串的 JavaScript 值。

旧版本。请使用 Buffer.from(data, ‘base64’) 代替。

提供该函数只是为了与传统网络平台 API 兼容,绝不应在新代码中使用,因为它们使用字符串表示二进制数据,而且在 JavaScript 中引入类型数组之前就已存在。对于使用 Node.js API 运行的代码,应使用 Buffer.from(str, ‘base64’) 和 buf.toString(‘base64’) 在 base64 编码字符串和二进制数据之间进行转换。

buffer.btoa(data) base64编码字符串

使用 Latin-1 (ISO-8859) 将字符串解码为字节,然后使用 Base64 将这些字节编码为字符串。
数据可以是任何可以强制转换成字符串的 JavaScript 值。

旧版本。使用 buf.toString(‘base64’) 代替。

提供该函数只是为了与传统网络平台 API 兼容,绝不应在新代码中使用,因为它们使用字符串表示二进制数据,而且在 JavaScript 中引入类型数组之前就已存在。对于使用 Node.js API 运行的代码,应使用 Buffer.from(str, ‘base64’) 和 buf.toString(‘base64’) 在 base64 编码字符串和二进制数据之间进行转换。

buffer.isAscii(input) 是否是ASCII数据

如果输入只包含有效的 ASCII 编码数据(包括输入为空的情况),则此函数返回 true。
如果输入是一个分离的数组缓冲区,则抛出该命令。

buffer.isUtf8(input) 是否是utf8数据

如果输入只包含有效的 UTF-8 编码数据(包括输入为空的情况),则此函数返回 true。
如果输入是一个分离的数组缓冲区,则抛出该命令。

buffer.INSPECT_MAX_BYTES

返回调用 buf.inspect() 时返回的最大字节数。用户模块可以重载该值。有关 buf.inspect() 行为的更多详情,请参阅 util.inspect()。

buffer.kMaxLength

buffer.constants.MAX_LENGTH 的别名。

buffer.kStringMaxLength

buffer.constants.MAX_STRING_LENGTH 的别名。

buffer.transcode(source, fromEnc, toEnc) 编码转换

参数:

  • source <Buffer> | <Uint8Array> 一个 Buffer 或 Uint8Array 实例。
  • fromEnc 当前编码。
  • toEnc 目标编码。

将给定的 Buffer 或 Uint8Array 实例从一种字符编码重新编码为另一种字符编码。返回一个新的 Buffer 实例。
如果 fromEnc 或 toEnc 指定的字符编码无效,或者不允许从 fromEnc 转换到 toEnc,则抛出该命令。
buffer.transcode()支持的编码有"ascii"、“utf8”、“utf16le”、“ucs2”、"latin1 "和 “二进制”。
如果给定的字节序列无法在目标编码中得到充分表达,转码过程将使用替换字符。例如

import { Buffer, transcode } from 'node:buffer';

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

由于欧元(€)符号不能用 US-ASCII 表示,因此在转码缓冲区中用 ? 代替。

Buffer constants 缓冲常量

buffer.constants.MAX_LENGTH 单个缓冲区实例允许的最大大小。

单个缓冲区实例允许的最大大小。

在 32 位架构上,该值目前为 2的30次方 - 1(约 1 GiB)。

在 64 位架构上,该值目前为2的32次方(约 4 GiB)。

它在v8引擎下反映了 v8::TypedArray::kMaxLength 的功能。

该值也可作为 buffer.kMaxLength 使用。

buffer.constants.MAX_STRING_LENGTH 单个字符串实例允许的最大长度。

单个字符串实例允许的最大长度。
代表字符串基元的最大长度,以 UTF-16 编码单位计算。

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

Buffer.from(), Buffer.alloc(), and Buffer.allocUnsafe()

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

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

由于 new Buffer() 的行为会根据第一个参数的类型而有所不同,因此,如果不执行参数验证或缓冲区初始化,就会无意中给应用程序带来安全性和可靠性问题。

例如,如果攻击者可以使应用程序接收一个数字,而预期接收的是一个字符串,那么应用程序可能会调用 new Buffer(100),而不是 new Buffer(“100”),从而导致分配一个 100 字节的缓冲区,而不是分配一个内容为 "100 "的 3 字节缓冲区。这种情况通常可以使用 JSON API 调用实现。由于 JSON 区分了数字和字符串类型,因此它允许注入数字,而没有对输入进行充分验证的天真编写的应用程序可能希望始终接收字符串。在 Node.js 8.0.0 之前,100 字节缓冲区可能包含任意预先存在的内存数据,因此可能被用于向远程攻击者暴露内存秘密。自 Node.js 8.0.0 起,由于数据是零填充的,因此不会发生内存泄露。不过,其他攻击仍有可能发生,例如导致服务器分配非常大的缓冲区,从而导致性能下降或在内存耗尽时崩溃。

为了使 Buffer 实例的创建更可靠、更不容易出错,新 Buffer() 构造函数的各种形式已被弃用,取而代之的是独立的 Buffer.from()、Buffer.alloc() 和 Buffer.allocUnsafe() 方法。

开发人员应将新 Buffer() 构造函数的所有现有使用迁移到这些新 API 之一。

  • 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 实例不包含潜在敏感的旧数据。如果 size 不是数字,将产生 TypeError。
  • Buffer.allocUnsafe(size) 和 Buffer.allocUnsafeSlow(size) 都会返回一个指定大小的新的未初始化 Buffer。由于 Buffer 是未初始化的,因此分配的内存段可能包含潜在敏感的旧数据。

如果 Buffer.allocUnsafe() 和 Buffer.from(array) 返回的缓冲实例大小小于或等于 Buffer.poolSize 的一半,则可以从共享内部内存池中分配。由 Buffer.allocsafeSlow() 返回的实例从不使用共享内部内存池。

The --zero-fill-buffers command-line option 零填充缓冲区命令行选项

可以使用 --zero-fill-buffers 命令行选项启动 Node.js,使所有新分配的缓冲区实例在创建时默认为零填充。如果不使用该选项,使用 Buffer.allocUnsafe()、Buffer.allocUnsafeSlow() 和 new SlowBuffer(size) 创建的缓冲区不会被清零。使用该标记会对性能产生明显的负面影响。只有在必要时才使用 --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.allocUnsafe() 有明显的性能优势,但必须格外小心,以避免在应用程序中引入安全漏洞。

结语

结束了。

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZSK6

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值