> ## Documentation Index
> Fetch the complete documentation index at: https://bun.ll1025.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 二进制数据

> 在 JavaScript 中处理二进制数据

Bun 实现了多种用于在 JavaScript 中处理二进制数据的数据类型和工具，其中大部分是 Web 标准。Bun 特有的 API 会特别注明。

此速查表兼作目录；单击左列中的类可跳转到其章节。

| 类                           | 描述                                                                                           |
| --------------------------- | -------------------------------------------------------------------------------------------- |
| [`TypedArray`](#typedarray) | 一系列类，提供类似 `Array` 的接口来与二进制数据交互。包括 `Uint8Array`、`Uint16Array`、`Int8Array` 等。                  |
| [`Buffer`](#buffer)         | `Uint8Array` 的子类，实现了广泛的便捷方法。与表中其他类不同，这是一个 Node.js API（Bun 实现了它）。在浏览器中不可用。                    |
| [`DataView`](#dataview)     | 一个类，提供用于在特定字节偏移量处向 `ArrayBuffer` 写入若干字节的 `get/set` API。常用于读取或写入二进制协议。                        |
| [`Blob`](#blob)             | 一个只读的二进制数据 blob，通常代表一个文件。具有 MIME `type`、`size`，以及转换为 `ArrayBuffer`、`ReadableStream` 和字符串的方法。 |
| [`File`](#file)             | `Blob` 的子类，代表一个文件。具有 `name` 和 `lastModified` 时间戳。Node.js v20 有实验性支持。                         |
| [`BunFile`](#bunfile)       | *仅 Bun。* `Blob` 的子类，代表磁盘上一个惰性加载的文件。使用 `Bun.file(path)` 创建。                                   |

***

## `ArrayBuffer` 和视图

JavaScript 直到 ECMAScript v5（2009）才引入处理二进制数据的机制。最基本的构建块是 `ArrayBuffer`，一个表示内存中字节序列的数据结构。

```ts theme={null}
// 此缓冲区可以存储 8 个字节
const buf = new ArrayBuffer(8);
```

尽管名称如此，但它不是一个数组，也不支持你可能期望的任何数组方法和操作符。你无法直接从 `ArrayBuffer` 读取或写入值；你只能检查其大小和从中创建"切片"。

```ts theme={null}
const buf = new ArrayBuffer(8);
buf.byteLength; // => 8

const slice = buf.slice(0, 4); // 返回新的 ArrayBuffer
slice.byteLength; // => 4
```

要读取或写入数据，你需要一个"视图"：一个\_包装\_ `ArrayBuffer` 实例的类，允许你读取和操作底层数据。有两种类型的视图：\_类型化数组\_和 `DataView`。

### `DataView`

`DataView` 类是一个较低级别的接口，用于读取和操作 `ArrayBuffer` 中的数据。

以下创建一个 `DataView` 并将第一个字节设置为 3。

```ts theme={null}
const buf = new ArrayBuffer(4);
// [0b00000000, 0b00000000, 0b00000000, 0b00000000]

const dv = new DataView(buf);
dv.setUint8(0, 3); // 在字节偏移量 0 处写入值 3
dv.getUint8(0); // => 3
// [0b00000011, 0b00000000, 0b00000000, 0b00000000]
```

接下来，在字节偏移量 `1` 处写入一个 `Uint16`。这需要两个字节。值 `513` 是 `2 * 256 + 1`；在字节中，即 `00000010 00000001`。

```ts theme={null}
dv.setUint16(1, 513);
// [0b00000011, 0b00000010, 0b00000001, 0b00000000]

console.log(dv.getUint16(1)); // => 513
```

底层 `ArrayBuffer` 的前三个字节现在已有值。尽管第二和第三个字节是用 `setUint16()` 写入的，你仍然可以使用 `getUint8()` 读取每个组件字节。

```ts theme={null}
console.log(dv.getUint8(1)); // => 2
console.log(dv.getUint8(2)); // => 1
```

写入的值需要的空间超过底层 `ArrayBuffer` 的大小时会抛出错误。以下在字节偏移量 `0` 处写入一个 `Float64`（需要 8 个字节），但缓冲区只有 4 个字节长。

```ts theme={null}
dv.setFloat64(0, 3.1415);
// ^ RangeError: 越界访问
```

以下方法在 `DataView` 上可用：

| 获取方法                                                                                                                       | 设置方法                                                                                                                       |
| -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [`getBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigInt64)   | [`setBigInt64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigInt64)   |
| [`getBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getBigUint64) | [`setBigUint64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setBigUint64) |
| [`getFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat32)     | [`setFloat32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat32)     |
| [`getFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getFloat64)     | [`setFloat64()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setFloat64)     |
| [`getInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt16)         | [`setInt16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt16)         |
| [`getInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt32)         | [`setInt32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt32)         |
| [`getInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt8)           | [`setInt8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setInt8)           |
| [`getUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint16)       | [`setUint16()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint16)       |
| [`getUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint32)       | [`setUint32()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint32)       |
| [`getUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getUint8)         | [`setUint8()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/setUint8)         |

### `TypedArray`

类型化数组是一系列类，提供类似 `Array` 的接口来与 `ArrayBuffer` 中的数据交互。`DataView` 允许你在特定偏移处写入不同大小的数字，而 `TypedArray` 将底层字节解释为固定大小的数字数组。

<Note>
  通常将这些类统称为它们的共享超类 `TypedArray`。这个类是 JavaScript
  \_内部\_的；你不能直接创建它的实例，而且 `TypedArray` 没有在全局作用域中定义。将其视为一个 `interface` 或抽象类。
</Note>

```ts theme={null}
const buffer = new ArrayBuffer(3);
const arr = new Uint8Array(buffer);

// 内容初始化为零
console.log(arr); // Uint8Array(3) [0, 0, 0]

// 像数组一样赋值
arr[0] = 0;
arr[1] = 10;
arr[2] = 255;
arr[3] = 255; // 无效，越界
```

类型化数组类，以及它们如何解释 `ArrayBuffer` 中的字节：

| 类                                                                                                                         | 描述                                                                                             |
| ------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)               | 每 1 个字节解释为一个无符号 8 位整数。范围 0 到 255。                                                              |
| [`Uint16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array)             | 每 2 个字节解释为一个无符号 16 位整数。范围 0 到 65535。                                                           |
| [`Uint32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)             | 每 4 个字节解释为一个无符号 32 位整数。范围 0 到 4294967295。                                                      |
| [`Int8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array)                 | 每 1 个字节解释为一个有符号 8 位整数。范围 -128 到 127。                                                           |
| [`Int16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array)               | 每 2 个字节解释为一个有符号 16 位整数。范围 -32768 到 32767。                                                      |
| [`Int32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array)               | 每 4 个字节解释为一个有符号 32 位整数。范围 -2147483648 到 2147483647。                                            |
| [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array)           | 每 2 个字节解释为一个 16 位浮点数。范围 -6.104e5 到 6.55e4。                                                     |
| [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array)           | 每 4 个字节解释为一个 32 位浮点数。范围 -3.4e38 到 3.4e38。                                                      |
| [`Float64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array)           | 每 8 个字节解释为一个 64 位浮点数。范围 -1.7e308 到 1.7e308。                                                    |
| [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)         | 每 8 个字节解释为一个有符号 `BigInt`。范围 -9223372036854775808 到 9223372036854775807（尽管 `BigInt` 能够表示更大的数字）。 |
| [`BigUint64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array)       | 每 8 个字节解释为一个无符号 `BigInt`。范围 0 到 18446744073709551615（尽管 `BigInt` 能够表示更大的数字）。                   |
| [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) | 与 `Uint8Array` 相同，但在给元素赋值时自动"钳制"到范围 0-255。                                                     |

下表显示了不同类型化数组类如何解释 `ArrayBuffer` 中的相同字节。

|                  | 字节 0                | 字节 1       | 字节 2                | 字节 3       | 字节 4                 | 字节 5       | 字节 6                 | 字节 7       |
| ---------------- | ------------------- | ---------- | ------------------- | ---------- | -------------------- | ---------- | -------------------- | ---------- |
| `ArrayBuffer`    | `00000000`          | `00000001` | `00000010`          | `00000011` | `00000100`           | `00000101` | `00000110`           | `00000111` |
| `Uint8Array`     | 0                   | 1          | 2                   | 3          | 4                    | 5          | 6                    | 7          |
| `Uint16Array`    | 256 (`1 * 256 + 0`) |            | 770 (`3 * 256 + 2`) |            | 1284 (`5 * 256 + 4`) |            | 1798 (`7 * 256 + 6`) |            |
| `Uint32Array`    | 50462976            |            |                     |            | 117835012            |            |                      |            |
| `BigUint64Array` | 506097522914230528n |            |                     |            |                      |            |                      |            |

从预定义的 `ArrayBuffer` 创建类型化数组：

```ts theme={null}
// 从 ArrayBuffer 创建类型化数组
const buf = new ArrayBuffer(10);
const arr = new Uint8Array(buf);

arr[0] = 30;
arr[1] = 60;

// 所有元素初始化为零
console.log(arr); // => Uint8Array(10) [ 30, 60, 0, 0, 0, 0, 0, 0, 0, 0 ];
```

从同一个 `ArrayBuffer` 实例化一个 `Uint32Array` 会抛出错误。

```ts theme={null}
const buf = new ArrayBuffer(10);
const arr = new Uint32Array(buf);
//          ^  RangeError: ArrayBuffer 长度减去 byteOffset
//             不是元素大小的倍数
```

一个 `Uint32` 值需要四个字节（32 位）。因为 `ArrayBuffer` 是 10 个字节长，所以无法将其内容干净地分为 4 字节块。

要解决此问题，在 `ArrayBuffer` 的特定"切片"上创建类型化数组。以下 `Uint32Array` 只"视图"底层 `ArrayBuffer` 的\_前\_ 8 个字节：`byteOffset` 为 `0`，`length` 为 `2`，即数组容纳的 `Uint32` 值的数量。

```ts theme={null}
// 从 ArrayBuffer 切片创建类型化数组
const buf = new ArrayBuffer(10);
const arr = new Uint32Array(buf, 0, 2);

/*
  buf    _ _ _ _ _ _ _ _ _ _    10 个字节
  arr   [_______,_______]       2 个 4 字节元素
*/

arr.byteOffset; // 0
arr.length; // 2
```

你不需要先创建一个 `ArrayBuffer` 实例；可以直接向类型化数组构造函数传递一个长度：

```ts theme={null}
const arr2 = new Uint8Array(5);

// 所有元素初始化为零
// => Uint8Array(5) [0, 0, 0, 0, 0]
```

类型化数组也可以直接从数字数组或其他类型化数组实例化：

```ts theme={null}
// 从数字数组
const arr1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
arr1[0]; // => 0;
arr1[7]; // => 7;

// 从另一个类型化数组
const arr2 = new Uint8Array(arr);
```

类型化数组提供与常规数组相同的方法，但有一些例外。例如，`push` 和 `pop` 不可用，因为它们需要调整底层 `ArrayBuffer` 的大小。

```ts theme={null}
const arr = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);

// 支持常见的数组方法
arr.filter(n => n > 128); // Uint8Array(1) [255]
arr.map(n => n * 2); // Uint8Array(8) [0, 2, 4, 6, 8, 10, 12, 14]
arr.reduce((acc, n) => acc + n, 0); // 28
arr.forEach(n => console.log(n)); // 0 1 2 3 4 5 6 7
arr.every(n => n < 10); // true
arr.find(n => n > 5); // 6
arr.includes(5); // true
arr.indexOf(5); // 5
```

有关类型化数组属性和方法的更多信息，请参阅 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray)。

### `Uint8Array`

`Uint8Array` 是 JavaScript 中最常见的类型化数组。它表示一个经典的"字节数组"：一个 0 到 255 之间的 8 位无符号整数序列。

在 Bun 中，它有在字节数组和 base64 或十六进制字符串表示之间进行转换的方法。

```ts theme={null}
new Uint8Array([1, 2, 3, 4, 5]).toBase64(); // "AQIDBAU="
Uint8Array.fromBase64("AQIDBAU="); // Uint8Array(5) [1, 2, 3, 4, 5]

new Uint8Array([255, 254, 253, 252, 251]).toHex(); // "fffefdfcfb"
Uint8Array.fromHex("fffefdfcfb"); // Uint8Array(5) [255, 254, 253, 252, 251]
```

它是 [`TextEncoder#encode`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder) 的返回值，以及 [`TextDecoder#decode`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder) 的输入类型，这两个工具类用于在字符串和各种二进制编码之间进行转换，最著名的是 `"utf-8"`。

```ts theme={null}
const encoder = new TextEncoder();
const bytes = encoder.encode("hello world");
// => Uint8Array(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ]

const decoder = new TextDecoder();
const text = decoder.decode(bytes);
// => hello world
```

### `Buffer`

Bun 实现了 `Buffer`，一个用于处理二进制数据的 Node.js API，它早于 JavaScript 规范中类型化数组的引入。后来它被重新实现为 `Uint8Array` 的子类。它提供了广泛的方法，包括多种类似 `Array` 和 `DataView` 的方法。

```ts theme={null}
const buf = Buffer.from("hello world");
// => Buffer(11) [ 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100 ]

buf.length; // => 11
buf[0]; // => 104, 'h' 的 ascii 码
buf.writeUInt8(72, 0); // => 'H' 的 ascii 码

console.log(buf.toString());
// => Hello world
```

请参阅 [Node.js 文档](https://nodejs.org/api/buffer.html)。

## `Blob`

`Blob` 是一个 Web API，常用于表示文件。它起源于浏览器（与 `ArrayBuffer` 不同，后者是 JavaScript 本身的一部分），但 Node.js 和 Bun 也支持它。

你很少直接创建 `Blob` 实例；它们通常来自外部源（如浏览器中的 `<input type="file">` 元素）或库。不过，你可以从一个或多个字符串或二进制"blob 部分"创建一个 `Blob`。

```ts theme={null}
const blob = new Blob(["<html>Hello</html>"], {
  type: "text/html",
});

blob.type; // => text/html
blob.size; // => 18
```

这些部分可以是 `string`、`ArrayBuffer`、`TypedArray`、`DataView` 或其他 `Blob` 实例。各个部分按给定的顺序连接。

```ts theme={null}
const blob = new Blob([
  "<html>",
  new Blob(["<body>"]),
  new Uint8Array([104, 101, 108, 108, 111]), // "hello" 的二进制形式
  "</body></html>",
]);
```

以多种格式异步读取 `Blob` 的内容。

```ts theme={null}
await blob.text(); // => <html><body>hello</body></html>
await blob.bytes(); // => Uint8Array（复制内容）
await blob.arrayBuffer(); // => ArrayBuffer（复制内容）
blob.stream(); // => ReadableStream
```

### `BunFile`

`BunFile` 是 `Blob` 的子类，表示磁盘上一个惰性加载的文件。与 `File` 一样，它添加了 `name` 和 `lastModified` 属性。与 `File` 不同的是，它不需要将文件加载到内存中。

```ts theme={null}
const file = Bun.file("index.txt");
// => BunFile
```

### `File`

[`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) 是 `Blob` 的子类，添加了 `name` 和 `lastModified` 属性。它在浏览器中常用于表示使用 `<input type="file">` 元素上传的文件。Node.js 和 Bun 实现了 `File`。

```ts theme={null}
// 在浏览器中！
// <input type="file" id="file" />

const files = document.getElementById("file").files;
// => File[]
```

```ts theme={null}
const file = new File(["<html>Hello</html>"], "index.html", {
  type: "text/html",
});
```

请参阅 [MDN 文档](https://developer.mozilla.org/en-US/docs/Web/API/Blob)。

***

## 流

流允许你处理二进制数据，而无需一次性全部加载到内存中。它们通常用于读取和写入文件、发送和接收网络请求，以及处理大量数据。

Bun 实现了 Web API [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) 和 [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream)。

<Note>
  Bun 也实现了 `node:stream` 模块，包括
  [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams)、
  [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams) 和
  [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams)。完整的文档请参考 Node.js 文档。
</Note>

要创建一个可读流：

```ts theme={null}
const stream = new ReadableStream({
  start(controller) {
    controller.enqueue("hello");
    controller.enqueue("world");
    controller.close();
  },
});
```

使用 `for await` 逐块读取流。

```ts theme={null}
for await (const chunk of stream) {
  console.log(chunk);
}

// => "hello"
// => "world"
```

有关 Bun 中流的更多信息，请参见 [流](/runtime/streams)。

***

## 转换

使用本节作为将一种二进制格式转换为另一种的参考。

### 从 `ArrayBuffer`

由于 `ArrayBuffer` 存储的是支撑其他二进制结构（如 `TypedArray`）的数据，以下代码片段并不是从 `ArrayBuffer` \_转换\_到另一种格式。相反，它们使用底层数据\_创建\_一个新实例。

#### 到 `TypedArray`

```ts theme={null}
new Uint8Array(buf);
```

#### 到 `DataView`

```ts theme={null}
new DataView(buf);
```

#### 到 `Buffer`

```ts theme={null}
// 在整个 ArrayBuffer 上创建 Buffer
Buffer.from(buf);

// 在 ArrayBuffer 的切片上创建 Buffer
Buffer.from(buf, 0, 10);
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
new TextDecoder().decode(buf);
```

#### 到 `number[]`

```ts theme={null}
Array.from(new Uint8Array(buf));
```

#### 到 `Blob`

```ts theme={null}
new Blob([buf], { type: "text/plain" });
```

#### 到 `ReadableStream`

以下代码片段创建一个 `ReadableStream` 并将整个 `ArrayBuffer` 作为一个数据块入队。

```ts theme={null}
new ReadableStream({
  start(controller) {
    controller.enqueue(buf);
    controller.close();
  },
});
```

<Accordion title="分块">
  要以数据块形式流式传输 `ArrayBuffer`，使用 `Uint8Array` 视图并将每个数据块入队。

  ```ts theme={null}
  const view = new Uint8Array(buf);
  const chunkSize = 1024;

  new ReadableStream({
    start(controller) {
      for (let i = 0; i < view.length; i += chunkSize) {
        controller.enqueue(view.slice(i, i + chunkSize));
      }
      controller.close();
    },
  });
  ```
</Accordion>

### 从 `TypedArray`

#### 到 `ArrayBuffer`

`buffer` 属性是底层的 `ArrayBuffer`。`TypedArray` 可能是该缓冲区\_切片\_的一个视图，因此大小可能不同。

```ts theme={null}
arr.buffer;
```

#### 到 `DataView`

要创建覆盖与 `TypedArray` 相同字节范围的 `DataView`：

```ts theme={null}
new DataView(arr.buffer, arr.byteOffset, arr.byteLength);
```

#### 到 `Buffer`

```ts theme={null}
Buffer.from(arr);
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
new TextDecoder().decode(arr);
```

#### 到 `number[]`

```ts theme={null}
Array.from(arr);
```

#### 到 `Blob`

```ts theme={null}
// 仅当 arr 是整个底层 TypedArray 的视图时
new Blob([arr.buffer], { type: "text/plain" });
```

#### 到 `ReadableStream`

```ts theme={null}
new ReadableStream({
  start(controller) {
    controller.enqueue(arr);
    controller.close();
  },
});
```

<Accordion title="分块">
  要以数据块形式流式传输 `ArrayBuffer`，将 `TypedArray` 分割成数据块并逐个入队。

  ```ts theme={null}
  new ReadableStream({
    start(controller) {
      for (let i = 0; i < arr.length; i += chunkSize) {
        controller.enqueue(arr.slice(i, i + chunkSize));
      }
      controller.close();
    },
  });
  ```
</Accordion>

### 从 `DataView`

#### 到 `ArrayBuffer`

```ts theme={null}
view.buffer;
```

#### 到 `TypedArray`

仅当 `DataView` 的 `byteLength` 是 `TypedArray` 子类的 `BYTES_PER_ELEMENT` 的倍数时才有效。

```ts theme={null}
new Uint8Array(view.buffer, view.byteOffset, view.byteLength);
new Uint16Array(view.buffer, view.byteOffset, view.byteLength / 2);
new Uint32Array(view.buffer, view.byteOffset, view.byteLength / 4);
// 等等...
```

#### 到 `Buffer`

```ts theme={null}
Buffer.from(view.buffer, view.byteOffset, view.byteLength);
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
new TextDecoder().decode(view);
```

#### 到 `number[]`

```ts theme={null}
Array.from(view);
```

#### 到 `Blob`

```ts theme={null}
new Blob([view.buffer], { type: "text/plain" });
```

#### 到 `ReadableStream`

```ts theme={null}
new ReadableStream({
  start(controller) {
    controller.enqueue(view.buffer);
    controller.close();
  },
});
```

<Accordion title="分块">
  要以数据块形式流式传输 `ArrayBuffer`，将 `DataView` 分割成数据块并逐个入队。

  ```ts theme={null}
  new ReadableStream({
    start(controller) {
      for (let i = 0; i < view.byteLength; i += chunkSize) {
        controller.enqueue(view.buffer.slice(i, i + chunkSize));
      }
      controller.close();
    },
  });
  ```
</Accordion>

### 从 `Buffer`

#### 到 `ArrayBuffer`

```ts theme={null}
buf.buffer;
```

#### 到 `TypedArray`

```ts theme={null}
new Uint8Array(buf);
```

#### 到 `DataView`

```ts theme={null}
new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
buf.toString();
```

作为 base64：

```ts theme={null}
buf.toString("base64");
```

作为十六进制：

```ts theme={null}
buf.toString("hex");
```

#### 到 `number[]`

```ts theme={null}
Array.from(buf);
```

#### 到 `Blob`

```ts theme={null}
new Blob([buf], { type: "text/plain" });
```

#### 到 `ReadableStream`

```ts theme={null}
new ReadableStream({
  start(controller) {
    controller.enqueue(buf);
    controller.close();
  },
});
```

<Accordion title="分块">
  要以数据块形式流式传输 `ArrayBuffer`，将 `Buffer` 分割成数据块并逐个入队。

  ```ts theme={null}
  new ReadableStream({
    start(controller) {
      for (let i = 0; i < buf.length; i += chunkSize) {
        controller.enqueue(buf.slice(i, i + chunkSize));
      }
      controller.close();
    },
  });
  ```
</Accordion>

### 从 `Blob`

#### 到 `ArrayBuffer`

```ts theme={null}
await blob.arrayBuffer();
```

#### 到 `TypedArray`

```ts theme={null}
await blob.bytes();
```

#### 到 `DataView`

```ts theme={null}
new DataView(await blob.arrayBuffer());
```

#### 到 `Buffer`

```ts theme={null}
Buffer.from(await blob.arrayBuffer());
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
await blob.text();
```

#### 到 `number[]`

```ts theme={null}
Array.from(await blob.bytes());
```

#### 到 `ReadableStream`

```ts theme={null}
blob.stream();
```

### 从 `ReadableStream`

[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) 是一个常见的中间件，用于将 `ReadableStream` 转换为其他格式。

```ts theme={null}
stream; // ReadableStream

const buffer = new Response(stream).arrayBuffer();
```

但这种方法很冗长，而且增加了不必要的开销。Bun 实现了优化的便捷函数，用于将 `ReadableStream` 转换为各种二进制格式。

#### 到 `ArrayBuffer`

```ts theme={null}
// 使用 Response
new Response(stream).arrayBuffer();

// 使用 Bun 函数
Bun.readableStreamToArrayBuffer(stream);
```

#### 到 `Uint8Array`

```ts theme={null}
// 使用 Response
new Response(stream).bytes();

// 使用 Bun 函数
Bun.readableStreamToBytes(stream);
```

#### 到 `TypedArray`

```ts theme={null}
// 使用 Response
const buf = await new Response(stream).arrayBuffer();
new Int8Array(buf);

// 使用 Bun 函数
new Int8Array(Bun.readableStreamToArrayBuffer(stream));
```

#### 到 `DataView`

```ts theme={null}
// 使用 Response
const buf = await new Response(stream).arrayBuffer();
new DataView(buf);

// 使用 Bun 函数
new DataView(Bun.readableStreamToArrayBuffer(stream));
```

#### 到 `Buffer`

```ts theme={null}
// 使用 Response
const buf = await new Response(stream).arrayBuffer();
Buffer.from(buf);

// 使用 Bun 函数
Buffer.from(Bun.readableStreamToArrayBuffer(stream));
```

#### 到 `string`

作为 UTF-8：

```ts theme={null}
// 使用 Response
await new Response(stream).text();

// 使用 Bun 函数
await Bun.readableStreamToText(stream);
```

#### 到 `number[]`

```ts theme={null}
// 使用 Response
const arr = await new Response(stream).bytes();
Array.from(arr);

// 使用 Bun 函数
Array.from(new Uint8Array(Bun.readableStreamToArrayBuffer(stream)));
```

Bun 提供了一个工具函数，用于将 `ReadableStream` 解析为其数据块数组。每个数据块可以是字符串、类型化数组或 `ArrayBuffer`。

```ts theme={null}
// 使用 Bun 函数
Bun.readableStreamToArray(stream);
```

#### 到 `Blob`

```ts theme={null}
new Response(stream).blob();
```

#### 到 `ReadableStream`

要将 `ReadableStream` 拆分为两个可以独立消费的流：

```ts theme={null}
const [a, b] = stream.tee();
```
