ArrayBuffer 和视图
JavaScript 直到 ECMAScript v5(2009)才引入处理二进制数据的机制。最基本的构建块是 ArrayBuffer,一个表示内存中字节序列的数据结构。
ArrayBuffer 读取或写入值;你只能检查其大小和从中创建”切片”。
ArrayBuffer 实例的类,允许你读取和操作底层数据。有两种类型的视图:_类型化数组_和 DataView。
DataView
DataView 类是一个较低级别的接口,用于读取和操作 ArrayBuffer 中的数据。
以下创建一个 DataView 并将第一个字节设置为 3。
1 处写入一个 Uint16。这需要两个字节。值 513 是 2 * 256 + 1;在字节中,即 00000010 00000001。
ArrayBuffer 的前三个字节现在已有值。尽管第二和第三个字节是用 setUint16() 写入的,你仍然可以使用 getUint8() 读取每个组件字节。
ArrayBuffer 的大小时会抛出错误。以下在字节偏移量 0 处写入一个 Float64(需要 8 个字节),但缓冲区只有 4 个字节长。
DataView 上可用:
TypedArray
类型化数组是一系列类,提供类似 Array 的接口来与 ArrayBuffer 中的数据交互。DataView 允许你在特定偏移处写入不同大小的数字,而 TypedArray 将底层字节解释为固定大小的数字数组。
通常将这些类统称为它们的共享超类
TypedArray。这个类是 JavaScript
_内部_的;你不能直接创建它的实例,而且 TypedArray 没有在全局作用域中定义。将其视为一个 interface 或抽象类。ArrayBuffer 中的字节:
下表显示了不同类型化数组类如何解释
ArrayBuffer 中的相同字节。
从预定义的
ArrayBuffer 创建类型化数组:
ArrayBuffer 实例化一个 Uint32Array 会抛出错误。
Uint32 值需要四个字节(32 位)。因为 ArrayBuffer 是 10 个字节长,所以无法将其内容干净地分为 4 字节块。
要解决此问题,在 ArrayBuffer 的特定”切片”上创建类型化数组。以下 Uint32Array 只”视图”底层 ArrayBuffer 的_前_ 8 个字节:byteOffset 为 0,length 为 2,即数组容纳的 Uint32 值的数量。
ArrayBuffer 实例;可以直接向类型化数组构造函数传递一个长度:
push 和 pop 不可用,因为它们需要调整底层 ArrayBuffer 的大小。
Uint8Array
Uint8Array 是 JavaScript 中最常见的类型化数组。它表示一个经典的”字节数组”:一个 0 到 255 之间的 8 位无符号整数序列。
在 Bun 中,它有在字节数组和 base64 或十六进制字符串表示之间进行转换的方法。
TextEncoder#encode 的返回值,以及 TextDecoder#decode 的输入类型,这两个工具类用于在字符串和各种二进制编码之间进行转换,最著名的是 "utf-8"。
Buffer
Bun 实现了 Buffer,一个用于处理二进制数据的 Node.js API,它早于 JavaScript 规范中类型化数组的引入。后来它被重新实现为 Uint8Array 的子类。它提供了广泛的方法,包括多种类似 Array 和 DataView 的方法。
Blob
Blob 是一个 Web API,常用于表示文件。它起源于浏览器(与 ArrayBuffer 不同,后者是 JavaScript 本身的一部分),但 Node.js 和 Bun 也支持它。
你很少直接创建 Blob 实例;它们通常来自外部源(如浏览器中的 <input type="file"> 元素)或库。不过,你可以从一个或多个字符串或二进制”blob 部分”创建一个 Blob。
string、ArrayBuffer、TypedArray、DataView 或其他 Blob 实例。各个部分按给定的顺序连接。
Blob 的内容。
BunFile
BunFile 是 Blob 的子类,表示磁盘上一个惰性加载的文件。与 File 一样,它添加了 name 和 lastModified 属性。与 File 不同的是,它不需要将文件加载到内存中。
File
File 是 Blob 的子类,添加了 name 和 lastModified 属性。它在浏览器中常用于表示使用 <input type="file"> 元素上传的文件。Node.js 和 Bun 实现了 File。
流
流允许你处理二进制数据,而无需一次性全部加载到内存中。它们通常用于读取和写入文件、发送和接收网络请求,以及处理大量数据。 Bun 实现了 Web APIReadableStream 和 WritableStream。
要创建一个可读流:
for await 逐块读取流。
转换
使用本节作为将一种二进制格式转换为另一种的参考。从 ArrayBuffer
由于 ArrayBuffer 存储的是支撑其他二进制结构(如 TypedArray)的数据,以下代码片段并不是从 ArrayBuffer _转换_到另一种格式。相反,它们使用底层数据_创建_一个新实例。
到 TypedArray
到 DataView
到 Buffer
到 string
作为 UTF-8:
到 number[]
到 Blob
到 ReadableStream
以下代码片段创建一个 ReadableStream 并将整个 ArrayBuffer 作为一个数据块入队。
分块
分块
要以数据块形式流式传输
ArrayBuffer,使用 Uint8Array 视图并将每个数据块入队。从 TypedArray
到 ArrayBuffer
buffer 属性是底层的 ArrayBuffer。TypedArray 可能是该缓冲区_切片_的一个视图,因此大小可能不同。
到 DataView
要创建覆盖与 TypedArray 相同字节范围的 DataView:
到 Buffer
到 string
作为 UTF-8:
到 number[]
到 Blob
到 ReadableStream
分块
分块
要以数据块形式流式传输
ArrayBuffer,将 TypedArray 分割成数据块并逐个入队。从 DataView
到 ArrayBuffer
到 TypedArray
仅当 DataView 的 byteLength 是 TypedArray 子类的 BYTES_PER_ELEMENT 的倍数时才有效。
到 Buffer
到 string
作为 UTF-8:
到 number[]
到 Blob
到 ReadableStream
分块
分块
要以数据块形式流式传输
ArrayBuffer,将 DataView 分割成数据块并逐个入队。从 Buffer
到 ArrayBuffer
到 TypedArray
到 DataView
到 string
作为 UTF-8:
到 number[]
到 Blob
到 ReadableStream
分块
分块
要以数据块形式流式传输
ArrayBuffer,将 Buffer 分割成数据块并逐个入队。从 Blob
到 ArrayBuffer
到 TypedArray
到 DataView
到 Buffer
到 string
作为 UTF-8:
到 number[]
到 ReadableStream
从 ReadableStream
Response 是一个常见的中间件,用于将 ReadableStream 转换为其他格式。
ReadableStream 转换为各种二进制格式。
到 ArrayBuffer
到 Uint8Array
到 TypedArray
到 DataView
到 Buffer
到 string
作为 UTF-8:
到 number[]
ReadableStream 解析为其数据块数组。每个数据块可以是字符串、类型化数组或 ArrayBuffer。
到 Blob
到 ReadableStream
要将 ReadableStream 拆分为两个可以独立消费的流: