Bun

二进制数据 (Binary data)

本页旨在介绍如何在 JavaScript 中使用二进制数据。Bun 实现了许多用于处理二进制数据的数据类型和实用程序,其中大多数是 Web 标准。任何 Bun 特有的 API 都会特别注明。(This page is intended as an introduction to working with binary data in JavaScript. Bun implements a number of data types and utilities for working with binary data, most of which are Web-standard. Any Bun-specific APIs will be noted as such.)

下面是一个快速“速查表”,同时也是目录。单击左列中的项目以跳转到该部分。(Below is a quick "cheat sheet" that doubles as a table of contents. Click an item in the left column to jump to that section.)

TypedArray一类类,提供类似 Array 的接口用于与二进制数据交互。包括 Uint8ArrayUint16ArrayInt8Array 等。(A family of classes that provide an Array-like interface for interacting with binary data. Includes Uint8Array, Uint16Array, Int8Array, and more.)
BufferUint8Array 的子类,实现了广泛的便利方法。与此表中的其他元素不同,这是一个 Node.js API(Bun 实现了它)。它不能在浏览器中使用。(A subclass of Uint8Array that implements a wide range of convenience methods. Unlike the other elements in this table, this is a Node.js API (which Bun implements). It can't be used in the browser.)
DataView一个类,提供 get/set API 用于在特定字节偏移量处向 ArrayBuffer 写入一些字节。常用于读取或写入二进制协议。(A class that provides a get/set API for writing some number of bytes to an ArrayBuffer at a particular byte offset. Often used reading or writing binary protocols.)
Blob二进制数据的只读 blob,通常表示文件。具有 MIME typesize 以及转换为 ArrayBufferReadableStream 和字符串的方法。(A readonly blob of binary data usually representing a file. Has a MIME type, a size, and methods for converting to ArrayBuffer, ReadableStream, and string.)
FileBlob 的子类,表示文件。具有 namelastModified 时间戳。Node.js v20 中有实验性支持。(A subclass of Blob that represents a file. Has a name and lastModified timestamp. There is experimental support in Node.js v20.)
BunFile仅限 BunBlob 的子类,表示磁盘上延迟加载的文件。使用 Bun.file(path) 创建。(Bun only. A subclass of Blob that represents a lazily-loaded file on disk. Created with Bun.file(path).)

ArrayBuffer 和视图 (and views)

在 2009 年之前,JavaScript 中没有语言原生的方法来存储和操作二进制数据。ECMAScript v5 引入了一系列用于此目的的新机制。最基本的构建块是 ArrayBuffer,它是一种简单的数据结构,表示内存中的字节序列。(Until 2009, there was no language-native way to store and manipulate binary data in JavaScript. ECMAScript v5 introduced a range of new mechanisms for this. The most fundamental building block is ArrayBuffer, a simple data structure that represents a sequence of bytes in memory.)

// this buffer can store 8 bytes
const buf = new ArrayBuffer(8);

尽管名称如此,但它不是数组,也不支持人们可能期望的任何数组方法和运算符。实际上,没有办法直接从 ArrayBuffer 读取或写入值。除了检查其大小和从中创建“切片”之外,您几乎无法对其执行任何操作。(Despite the name, it isn't an array and supports none of the array methods and operators one might expect. In fact, there is no way to directly read or write values from an ArrayBuffer. There's very little you can do with one except check its size and create "slices" from it.)

const buf = new ArrayBuffer(8);
buf.byteLength; // => 8

const slice = buf.slice(0, 4); // returns new ArrayBuffer
slice.byteLength; // => 4

为了做任何有趣的事情,我们需要一个称为“视图”的构造。视图是一个类,它包装 ArrayBuffer 实例,并允许您读取和操作底层数据。有两种类型的视图:类型化数组DataView。(To do anything interesting we need a construct known as a "view". A view is a class that *wraps* an ArrayBuffer instance and lets you read and manipulate the underlying data. There are two types of views: *typed arrays* and DataView.)

DataView

DataView 类是用于读取和操作 ArrayBuffer 中数据的较低级别接口。(The DataView class is a lower-level interface for reading and manipulating the data in an ArrayBuffer.)

下面我们创建一个新的 DataView 并将第一个字节设置为 3。(Below we create a new DataView and set the first byte to 3.)

const buf = new ArrayBuffer(4);
// [0b00000000, 0b00000000, 0b00000000, 0b00000000]

const dv = new DataView(buf);
dv.setUint8(0, 3); // write value 3 at byte offset 0
dv.getUint8(0); // => 3
// [0b00000011, 0b00000000, 0b00000000, 0b00000000]

现在让我们在字节偏移量 1 处写入一个 Uint16。这需要两个字节。我们使用值 513,即 2 * 256 + 1;以字节为单位,即 00000010 00000001。(Now let's write a Uint16 at byte offset 1. This requires two bytes. We're using the value 513, which is 2 * 256 + 1; in bytes, that's 00000010 00000001.)

dv.setUint16(1, 513);
// [0b00000011, 0b00000010, 0b00000001, 0b00000000]

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

我们现在已经为底层 ArrayBuffer 中的前三个字节分配了一个值。即使第二个和第三个字节是使用 setUint16() 创建的,我们仍然可以使用 getUint8() 读取它的每个组成字节。(We've now assigned a value to the first three bytes in our underlying ArrayBuffer. Even though the second and third bytes were created using setUint16(), we can still read each of its component bytes using getUint8().)

console.log(dv.getUint8(1)); // => 2
console.log(dv.getUint8(2)); // => 1

尝试写入的值需要的空间超过底层 ArrayBuffer 中可用的空间将导致错误。下面我们尝试在字节偏移量 0 处写入一个 Float64(需要 8 个字节),但缓冲区中总共只有四个字节。(Attempting to write a value that requires more space than is available in the underlying ArrayBuffer will cause an error. Below we attempt to write a Float64 (which requires 8 bytes) at byte offset 0, but there are only four total bytes in the buffer.)

dv.setFloat64(0, 3.1415);
// ^ RangeError: Out of bounds access

DataView 上可以使用以下方法 (The following methods are available on DataView)

TypedArray

类型化数组是一类类,提供类似 Array 的接口用于与 ArrayBuffer 中的数据交互。DataView 允许您在特定偏移量处写入不同大小的数字,而 TypedArray 将底层字节解释为数字数组,每个数字的大小固定。(Typed arrays are a family of classes that provide an Array-like interface for interacting with data in an ArrayBuffer. Whereas a DataView lets you write numbers of varying size at a particular offset, a TypedArray interprets the underlying bytes as an array of numbers, each of a fixed size.)

注意 — 通常通过它们共享的超类 TypedArray 来统称此类类。此类是 JavaScript 的内部类;您无法直接创建它的实例,并且 TypedArray 未在全局作用域中定义。将其视为 interface 或抽象类。(Note — It's common to refer to this family of classes collectively by their shared superclass TypedArray. This class as *internal* to JavaScript; you can't directly create instances of it, and TypedArray is not defined in the global scope. Think of it as an interface or an abstract class.)

const buffer = new ArrayBuffer(3);
const arr = new Uint8Array(buffer);

// contents are initialized to zero
console.log(arr); // Uint8Array(3) [0, 0, 0]

// assign values like an array
arr[0] = 0;
arr[1] = 10;
arr[2] = 255;
arr[3] = 255; // no-op, out of bounds

虽然 ArrayBuffer 是通用的字节序列,但这些类型化数组类将字节解释为给定字节大小的数字数组。(While an ArrayBuffer is a generic sequence of bytes, these typed array classes interpret the bytes as an array of numbers of a given byte size.) 顶行包含原始字节,后面的行包含当使用不同的类型化数组类查看时,这些字节将如何解释。(The top row contains the raw bytes, and the later rows contain how these bytes will be interpreted when viewed using different typed array classes.)

以下类是类型化数组,以及它们如何解释 ArrayBuffer 中的字节的描述 (The following classes are typed arrays, along with a description of how they interpret the bytes in an ArrayBuffer)

类 (Class)描述 (Description)
Uint8Array每个(1)字节被解释为无符号 8 位整数。范围 0 到 255。(Every one (1) byte is interpreted as an unsigned 8-bit integer. Range 0 to 255.)
Uint16Array每两个(2)字节被解释为无符号 16 位整数。范围 0 到 65535。(Every two (2) bytes are interpreted as an unsigned 16-bit integer. Range 0 to 65535.)
Uint32Array每四个(4)字节被解释为无符号 32 位整数。范围 0 到 4294967295。(Every four (4) bytes are interpreted as an unsigned 32-bit integer. Range 0 to 4294967295.)
Int8Array每个(1)字节被解释为有符号 8 位整数。范围 -128 到 127。(Every one (1) byte is interpreted as a signed 8-bit integer. Range -128 to 127.)
Int16Array每两个(2)字节被解释为有符号 16 位整数。范围 -32768 到 32767。(Every two (2) bytes are interpreted as a signed 16-bit integer. Range -32768 to 32767.)
Int32Array每四个(4)字节被解释为有符号 32 位整数。范围 -2147483648 到 2147483647。(Every four (4) bytes are interpreted as a signed 32-bit integer. Range -2147483648 to 2147483647.)
Float16Array每两个(2)字节被解释为 16 位浮点数。范围 -6.104e5 到 6.55e4。(Every two (2) bytes are interpreted as a 16-bit floating point number. Range -6.104e5 to 6.55e4.)
Float32Array每四个(4)字节被解释为 32 位浮点数。范围 -3.4e38 到 3.4e38。(Every four (4) bytes are interpreted as a 32-bit floating point number. Range -3.4e38 to 3.4e38.)
Float64Array每八个(8)字节被解释为 64 位浮点数。范围 -1.7e308 到 1.7e308。(Every eight (8) bytes are interpreted as a 64-bit floating point number. Range -1.7e308 to 1.7e308.)
BigInt64Array每八个(8)字节被解释为有符号 BigInt。范围 -9223372036854775808 到 9223372036854775807(尽管 BigInt 能够表示更大的数字)。(Every eight (8) bytes are interpreted as a signed BigInt. Range -9223372036854775808 to 9223372036854775807 (though BigInt is capable of representing larger numbers).)
BigUint64Array每八个(8)字节被解释为无符号 BigInt。范围 0 到 18446744073709551615(尽管 BigInt 能够表示更大的数字)。(Every eight (8) bytes are interpreted as an unsigned BigInt. Range 0 to 18446744073709551615 (though BigInt is capable of representing larger numbers).)
Uint8ClampedArrayUint8Array 相同,但在为元素赋值时会自动“钳制”到 0-255 范围。(Same as Uint8Array, but automatically "clamps" to the range 0-255 when assigning a value to an element.)

下表演示了当使用不同的类型化数组类查看时,ArrayBuffer 中的字节是如何解释的。(The table below demonstrates how the bytes in an ArrayBuffer are interpreted when viewed using different typed array classes.)

ArrayBuffer0000000000000001000000100000001100000100000001010000011000000111
Uint8Array01234567
Uint16Array256 (1 * 256 + 0) 770 (3 * 256 + 2) 1284 (5 * 256 + 4) 1798 (7 * 256 + 6)
Uint32Array50462976 117835012
BigUint64Array506097522914230528n

要从预定义的 ArrayBuffer 创建类型化数组 (To create a typed array from a pre-defined ArrayBuffer)

// create typed array from ArrayBuffer
const buf = new ArrayBuffer(10);
const arr = new Uint8Array(buf);

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

// all elements are initialized to zero
console.log(arr); // => Uint8Array(10) [ 30, 60, 0, 0, 0, 0, 0, 0, 0, 0 ];

如果我们尝试从同一个 ArrayBuffer 实例化 Uint32Array,我们会收到一个错误。(If we tried to instantiate a Uint32Array from this same ArrayBuffer, we'd get an error.)

const buf = new ArrayBuffer(10);
const arr = new Uint32Array(buf);
//          ^  RangeError: ArrayBuffer length minus the byteOffset
//             is not a multiple of the element size

一个 Uint32 值需要四个字节(16 位)。由于 ArrayBuffer 长 10 个字节,因此无法将其内容干净地划分为 4 字节块。(A Uint32 value requires four bytes (16 bits). Because the ArrayBuffer is 10 bytes long, there's no way to cleanly divide its contents into 4-byte chunks.)

为了解决这个问题,我们可以在 ArrayBuffer 的特定“切片”上创建一个类型化数组。下面的 Uint16Array 仅“查看”底层 ArrayBuffer 8 个字节。为了实现这些,我们指定 byteOffset0length2,这表示我们希望数组容纳的 Uint32 数字的数量。(To fix this, we can create a typed array over a particular "slice" of an ArrayBuffer. The Uint16Array below only "views" the *first* 8 bytes of the underlying ArrayBuffer. To achieve these, we specify a byteOffset of 0 and a length of 2, which indicates the number of Uint32 numbers we want our array to hold.)

// create typed array from ArrayBuffer slice
const buf = new ArrayBuffer(10);
const arr = new Uint32Array(buf, 0, 2);

/*
  buf    _ _ _ _ _ _ _ _ _ _    10 bytes
  arr   [_______,_______]       2 4-byte elements
*/

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

您无需显式创建 ArrayBuffer 实例;您可以改为直接在类型化数组构造函数中指定长度 (You don't need to explicitly create an ArrayBuffer instance; you can instead directly specify a length in the typed array constructor)

const arr2 = new Uint8Array(5);

// all elements are initialized to zero
// => Uint8Array(5) [0, 0, 0, 0, 0]

类型化数组也可以直接从数字数组或其他类型化数组实例化 (Typed arrays can also be instantiated directly from an array of numbers, or another typed array)

// from an array of numbers
const arr1 = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);
arr1[0]; // => 0;
arr1[7]; // => 7;

// from another typed array
const arr2 = new Uint8Array(arr);

广义上讲,类型化数组提供与常规数组相同的方法,但有一些例外。例如,pushpop 在类型化数组上不可用,因为它们需要调整底层 ArrayBuffer 的大小。(Broadly speaking, typed arrays provide the same methods as regular arrays, with a few exceptions. For example, push and pop are not available on typed arrays, because they would require resizing the underlying ArrayBuffer.)

const arr = new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7]);

// supports common array methods
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 文档。(Refer to the MDN documentation for more information on the properties and methods of typed arrays.)

Uint8Array

值得特别强调 Uint8Array,因为它代表经典的“字节数组”——0 到 255 之间的 8 位无符号整数序列。这是您在 JavaScript 中最常见的类型化数组。(It's worth specifically highlighting Uint8Array, as it represents a classic "byte array"—a sequence of 8-bit unsigned integers between 0 and 255. This is the most common typed array you'll encounter in JavaScript.)

在 Bun 中,以及在未来的其他 JavaScript 引擎中,它具有在字节数组和这些数组的序列化表示(如 base64 或十六进制字符串)之间进行转换的方法。(In Bun, and someday in other JavaScript engines, it has methods available for converting between byte arrays and serialized representations of those arrays as base64 or hex strings.)

new Uint8Array([1, 2, 3, 4, 5]).toBase64(); // "AQIDBA=="
Uint8Array.fromBase64("AQIDBA=="); // Uint8Array(4) [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 的返回值,以及 TextDecoder#decode 的输入类型,这两个实用程序类旨在转换字符串和各种二进制编码,最著名的是 "utf-8"。(It is the return value of TextEncoder#encode, and the input type of TextDecoder#decode, two utility classes designed to translate strings and various binary encodings, most notably "utf-8".)

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 的方法。(Bun implements Buffer, a Node.js API for working with binary data that pre-dates the introduction of typed arrays in the JavaScript spec. It has since been re-implemented as a subclass of Uint8Array. It provides a wide range of methods, including several Array-like and DataView-like methods.)

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, ascii for 'h'
buf.writeUInt8(72, 0); // => ascii for 'H'

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

有关完整文档,请参阅 Node.js 文档。(For complete documentation, refer to the Node.js documentation.)

Blob

Blob 是一个 Web API,通常用于表示文件。Blob 最初在浏览器中实现(与作为 JavaScript 本身一部分的 ArrayBuffer 不同),但现在 Node 和 Bun 也支持它。(Blob is a Web API commonly used for representing files. Blob was initially implemented in browsers (unlike ArrayBuffer which is part of JavaScript itself), but it is now supported in Node and Bun.)

直接创建 Blob 实例并不常见。更常见的情况是,您将从外部来源(例如浏览器中的 <input type="file"> 元素)或库接收 Blob 实例。也就是说,可以从一个或多个字符串或二进制“blob 部分”创建 Blob。(It isn't common to directly create Blob instances. More often, you'll receive instances of Blob from an external source (like an <input type="file"> element in the browser) or library. That said, it is possible to create a Blob from one or more string or binary "blob parts".)

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

blob.type; // => text/html
blob.size; // => 19

这些部分可以是 stringArrayBufferTypedArrayDataView 或其他 Blob 实例。blob 部分按照提供的顺序连接在一起。(These parts can be string, ArrayBuffer, TypedArray, DataView, or other Blob instances. The blob parts are concatenated together in the order they are provided.)

const blob = new Blob([
  "<html>",
  new Blob(["<body>"]),
  new Uint8Array([104, 101, 108, 108, 111]), // "hello" in binary
  "</body></html>",
]);

Blob 的内容可以以异步方式以各种格式读取。(The contents of a Blob can be asynchronously read in various formats.)

await blob.text(); // => <html><body>hello</body></html>
await blob.bytes(); // => Uint8Array (copies contents)
await blob.arrayBuffer(); // => ArrayBuffer (copies contents)
await blob.stream(); // => ReadableStream

BunFile

BunFileBlob 的子类,用于表示磁盘上延迟加载的文件。与 File 类似,它添加了 namelastModified 属性。与 File 不同,它不需要将文件加载到内存中。(BunFile is a subclass of Blob used to represent a lazily-loaded file on disk. Like File, it adds a name and lastModified property. Unlike File, it does not require the file to be loaded into memory.)

const file = Bun.file("index.txt");
// => BunFile

File

仅限浏览器。Node.js 20 中的实验性支持。(Browser only. Experimental support in Node.js 20.)

FileBlob 的子类,它添加了 namelastModified 属性。它通常在浏览器中使用,以表示通过 <input type="file"> 元素上传的文件。Node.js 和 Bun 实现了 File。(File is a subclass of Blob that adds a name and lastModified property. It's commonly used in the browser to represent files uploaded via a <input type="file"> element. Node.js and Bun implement File.)

// on browser!
// <input type="file" id="file" />

const files = document.getElementById("file").files;
// => File[]
const file = new File(["<html>Hello</html>"], "index.html", {
  type: "text/html",
});

有关完整的文档信息,请参阅 MDN 文档。(Refer to the MDN documentation for complete docs information.)

流 (Streams)

流是用于处理二进制数据而不一次性将其全部加载到内存中的重要抽象。它们通常用于读取和写入文件、发送和接收网络请求以及处理大量数据。(Streams are an important abstraction for working with binary data without loading it all into memory at once. They are commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data.)

Bun 实现了 Web API ReadableStreamWritableStream。(Bun implements the Web APIs ReadableStream and WritableStream.)

Bun 还实现了 node:stream 模块,包括 ReadableWritableDuplex。有关完整文档,请参阅 Node.js 文档。(Bun also implements the node:stream module, including Readable, Writable, and Duplex. For complete documentation, refer to the Node.js docs.)

要创建一个简单的可读流 (To create a simple readable stream)

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

此流的内容可以使用 for await 语法逐块读取。(The contents of this stream can be read chunk-by-chunk with for await syntax.)

for await (const chunk of stream) {
  console.log(chunk);
  // => "hello"
  // => "world"
}

有关 Bun 中流的更完整讨论,请参阅 API > 流 (Streams)。(For a more complete discussion of streams in Bun, see API > Streams.)

转换 (Conversion)

从一种二进制格式转换为另一种二进制格式是一项常见的任务。本节旨在作为参考。(Converting from one binary format to another is a common task. This section is intended as a reference.)

ArrayBuffer (From ArrayBuffer)

由于 ArrayBuffer 存储了其他二进制结构(如 TypedArray)的底层数据,因此以下代码片段不是从 ArrayBuffer转换为另一种格式。相反,它们是创建使用存储的底层数据的新实例。(Since ArrayBuffer stores the data that underlies other binary structures like TypedArray, the snippets below are not converting from ArrayBuffer to another format. Instead, they are creating a new instance using the data stored underlying data.)

转换为 TypedArray (To TypedArray)

new Uint8Array(buf);

转换为 DataView (To DataView)

new DataView(buf);

转换为 Buffer (To Buffer)

// create Buffer over entire ArrayBuffer
Buffer.from(buf);

// create Buffer over a slice of the ArrayBuffer
Buffer.from(buf, 0, 10);

转换为 string (To string)

作为 UTF-8 (As UTF-8)

new TextDecoder().decode(buf);

转换为 number[] (To number[])

Array.from(new Uint8Array(buf));

转换为 Blob (To Blob)

new Blob([buf], { type: "text/plain" });

转换为 ReadableStream (To ReadableStream)

以下代码片段创建一个 ReadableStream 并将整个 ArrayBuffer 作为单个块排队。(The following snippet creates a ReadableStream and enqueues the entire ArrayBuffer as a single chunk.)

new ReadableStream({
  start(controller) {
    controller.enqueue(buf);
    controller.close();
  },
});

使用分块 (With chunking)

TypedArray (From TypedArray)

转换为 ArrayBuffer (To ArrayBuffer)

这将检索底层 ArrayBuffer。请注意,TypedArray 可以是底层缓冲区的切片的视图,因此大小可能不同。(This retrieves the underlying ArrayBuffer. Note that a TypedArray can be a view of a slice of the underlying buffer, so the sizes may differ.)

arr.buffer;

转换为 DataView (To DataView)

创建覆盖与 TypedArray 相同字节范围的 DataView。(To creates a DataView over the same byte range as the TypedArray.)

new DataView(arr.buffer, arr.byteOffset, arr.byteLength);

转换为 Buffer (To Buffer)

Buffer.from(arr);

转换为 string (To string)

作为 UTF-8 (As UTF-8)

new TextDecoder().decode(arr);

转换为 number[] (To number[])

Array.from(arr);

转换为 Blob (To Blob)

// only if arr is a view of its entire backing TypedArray
new Blob([arr.buffer], { type: "text/plain" });

转换为 ReadableStream (To ReadableStream)

new ReadableStream({
  start(controller) {
    controller.enqueue(arr);
    controller.close();
  },
});

使用分块 (With chunking)

DataView (From DataView)

转换为 ArrayBuffer (To ArrayBuffer)

view.buffer;

转换为 TypedArray (To TypedArray)

仅当 DataViewbyteLengthTypedArray 子类的 BYTES_PER_ELEMENT 的倍数时才有效。(Only works if the byteLength of the DataView is a multiple of the BYTES_PER_ELEMENT of the TypedArray subclass.)

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);
// etc...

转换为 Buffer (To Buffer)

Buffer.from(view.buffer, view.byteOffset, view.byteLength);

转换为 string (To string)

作为 UTF-8 (As UTF-8)

new TextDecoder().decode(view);

转换为 number[] (To number[])

Array.from(view);

转换为 Blob (To Blob)

new Blob([view.buffer], { type: "text/plain" });

转换为 ReadableStream (To ReadableStream)

new ReadableStream({
  start(controller) {
    controller.enqueue(view.buffer);
    controller.close();
  },
});

使用分块 (With chunking)

Buffer (From Buffer)

转换为 ArrayBuffer (To ArrayBuffer)

buf.buffer;

转换为 TypedArray (To TypedArray)

new Uint8Array(buf);

转换为 DataView (To DataView)

new DataView(buf.buffer, buf.byteOffset, buf.byteLength);

转换为 string (To string)

作为 UTF-8 (As UTF-8)

buf.toString();

作为 base64 (As base64)

buf.toString('base64');

作为十六进制 (As hex)

buf.toString('hex');

转换为 number[] (To number[])

Array.from(buf);

转换为 Blob (To Blob)

new Blob([buf], { type: "text/plain" });

转换为 ReadableStream (To ReadableStream)

new ReadableStream({
  start(controller) {
    controller.enqueue(buf);
    controller.close();
  },
});

使用分块 (With chunking)

Blob (From Blob)

转换为 ArrayBuffer (To ArrayBuffer)

Blob 类为此目的提供了一种便捷方法。(The Blob class provides a convenience method for this purpose.)

await blob.arrayBuffer();

转换为 TypedArray (To TypedArray)

await blob.bytes();

转换为 DataView (To DataView)

new DataView(await blob.arrayBuffer());

转换为 Buffer (To Buffer)

Buffer.from(await blob.arrayBuffer());

转换为 string (To string)

作为 UTF-8 (As UTF-8)

await blob.text();

转换为 number[] (To number[])

Array.from(await blob.bytes());

转换为 ReadableStream (To ReadableStream)

blob.stream();

ReadableStream (From ReadableStream)

通常使用 Response 作为方便的中间表示,以更轻松地将 ReadableStream 转换为其他格式。(It's common to use Response as a convenient intermediate representation to make it easier to convert ReadableStream to other formats.)

stream; // ReadableStream

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

但是,这种方法很冗长,并且增加了不必要的开销,从而降低了整体性能。Bun 实现了一组优化的便捷函数,用于将 ReadableStream 转换为各种二进制格式。(However this approach is verbose and adds overhead that slows down overall performance unnecessarily. Bun implements a set of optimized convenience functions for converting ReadableStream various binary formats.)

转换为 ArrayBuffer (To ArrayBuffer)

// with Response
new Response(stream).arrayBuffer();

// with Bun function
Bun.readableStreamToArrayBuffer(stream);

转换为 Uint8Array (To Uint8Array)

// with Response
new Response(stream).bytes();

// with Bun function
Bun.readableStreamToBytes(stream);

转换为 TypedArray (To TypedArray)

// with Response
const buf = await new Response(stream).arrayBuffer();
new Int8Array(buf);

// with Bun function
new Int8Array(Bun.readableStreamToArrayBuffer(stream));

转换为 DataView (To DataView)

// with Response
const buf = await new Response(stream).arrayBuffer();
new DataView(buf);

// with Bun function
new DataView(Bun.readableStreamToArrayBuffer(stream));

转换为 Buffer (To Buffer)

// with Response
const buf = await new Response(stream).arrayBuffer();
Buffer.from(buf);

// with Bun function
Buffer.from(Bun.readableStreamToArrayBuffer(stream));

转换为 string (To string)

作为 UTF-8 (As UTF-8)

// with Response
await new Response(stream).text();

// with Bun function
await Bun.readableStreamToText(stream);

转换为 number[] (To number[])

// with Response
const arr = await new Response(stream).bytes();
Array.from(arr);

// with Bun function
Array.from(new Uint8Array(Bun.readableStreamToArrayBuffer(stream)));

Bun 提供了一个实用程序,用于将 ReadableStream 解析为其块数组。每个块可以是字符串、类型化数组或 ArrayBuffer。(Bun provides a utility for resolving a ReadableStream to an array of its chunks. Each chunk may be a string, typed array, or ArrayBuffer.)

// with Bun function
Bun.readableStreamToArray(stream);

转换为 Blob (To Blob)

new Response(stream).blob();

转换为 ReadableStream (To ReadableStream)

要将 ReadableStream 拆分为两个可以独立使用的流 (To split a ReadableStream into two streams that can be consumed independently)

const [a, b] = stream.tee();