---
title: Binary Data
description: Working with binary data in JavaScript
---

Bun implements several data types and utilities for working with binary data in JavaScript, most of which are Web-standard. Bun-specific APIs are noted as such.

This cheat sheet doubles as a table of contents; click a class in the left column to jump to its section.

| Class                       | Description                                                                                                                                                                                    |
| --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`TypedArray`](#typedarray) | A family of classes that provide an `Array`-like interface for interacting with binary data. Includes `Uint8Array`, `Uint16Array`, `Int8Array`, and more.                                      |
| [`Buffer`](#buffer)         | A subclass of `Uint8Array` that implements a wide range of convenience methods. Unlike the others in this table, it's a Node.js API (which Bun implements). It isn't available in the browser. |
| [`DataView`](#dataview)     | A class that provides a `get/set` API for writing some number of bytes to an `ArrayBuffer` at a particular byte offset. Often used for reading or writing binary protocols.                    |
| [`Blob`](#blob)             | 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.                            |
| [`File`](#file)             | A subclass of `Blob` that represents a file. Has a `name` and `lastModified` timestamp. Node.js v20 has experimental support.                                                                  |
| [`BunFile`](#bunfile)       | _Bun only_. A subclass of `Blob` that represents a lazily-loaded file on disk. Created with `Bun.file(path)`.                                                                                  |

---

## `ArrayBuffer` and views

JavaScript had no language-native way to store and manipulate binary data until ECMAScript v5 (2009) introduced a range of mechanisms for it. The most fundamental building block is `ArrayBuffer`, a data structure that represents a sequence of bytes in memory.

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

Despite the name, it isn't an array and supports none of the array methods and operators you might expect. You can't read or write values from an `ArrayBuffer` directly; all you can do is check its size and create "slices" from it.

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

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

To read or write the data, you need a "view": 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`

The `DataView` class is a lower-level interface for reading and manipulating the data in an `ArrayBuffer`.

The following creates a `DataView` and sets the first byte to 3.

```ts
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]
```

Next, write a `Uint16` at byte offset `1`. This requires two bytes. The value `513` is `2 * 256 + 1`; in bytes, that's `00000010 00000001`.

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

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

The first three bytes of the underlying `ArrayBuffer` now have values. Even though the second and third bytes were written with `setUint16()`, you can still read each component byte with `getUint8()`.

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

Writing a value that needs more space than the underlying `ArrayBuffer` has throws an error. The following writes a `Float64` (which requires 8 bytes) at byte offset `0`, but the buffer is only four bytes long.

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

The following methods are available on `DataView`:

| Getters                                                                                                                    | Setters                                                                                                                    |
| -------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [`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`

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.

<Note>
  It's common to refer to this family of classes collectively by their shared superclass `TypedArray`. This class is
  _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.
</Note>

```ts
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
```

The typed array classes, and how each interprets the bytes in an `ArrayBuffer`:

| Class                                                                                                                     | Description                                                                                                                                                                |
| ------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`Uint8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array)               | Every one (1) byte is interpreted as an unsigned 8-bit integer. Range 0 to 255.                                                                                            |
| [`Uint16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array)             | Every two (2) bytes are interpreted as an unsigned 16-bit integer. Range 0 to 65535.                                                                                       |
| [`Uint32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array)             | Every four (4) bytes are interpreted as an unsigned 32-bit integer. Range 0 to 4294967295.                                                                                 |
| [`Int8Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array)                 | Every one (1) byte is interpreted as a signed 8-bit integer. Range -128 to 127.                                                                                            |
| [`Int16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array)               | Every two (2) bytes are interpreted as a signed 16-bit integer. Range -32768 to 32767.                                                                                     |
| [`Int32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array)               | Every four (4) bytes are interpreted as a signed 32-bit integer. Range -2147483648 to 2147483647.                                                                          |
| [`Float16Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float16Array)           | Every two (2) bytes are interpreted as a 16-bit floating point number. Range -6.104e5 to 6.55e4.                                                                           |
| [`Float32Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array)           | Every four (4) bytes are interpreted as a 32-bit floating point number. Range -3.4e38 to 3.4e38.                                                                           |
| [`Float64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array)           | Every eight (8) bytes are interpreted as a 64-bit floating point number. Range -1.7e308 to 1.7e308.                                                                        |
| [`BigInt64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt64Array)         | Every eight (8) bytes are interpreted as a signed `BigInt`. Range -9223372036854775808 to 9223372036854775807 (though `BigInt` is capable of representing larger numbers). |
| [`BigUint64Array`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigUint64Array)       | Every eight (8) bytes are interpreted as an unsigned `BigInt`. Range 0 to 18446744073709551615 (though `BigInt` is capable of representing larger numbers).                |
| [`Uint8ClampedArray`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray) | Same as `Uint8Array`, but automatically "clamps" to the range 0-255 when assigning a value to an element.                                                                  |

The following table shows how the same bytes in an `ArrayBuffer` are interpreted by different typed array classes.

|                  | Byte 0              | Byte 1     | Byte 2              | Byte 3     | Byte 4               | Byte 5     | Byte 6               | Byte 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 |            |                     |            |                      |            |                      |            |

To create a typed array from a pre-defined `ArrayBuffer`:

```ts
// 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 ];
```

Instantiating a `Uint32Array` from this same `ArrayBuffer` throws an error.

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

A `Uint32` value requires four bytes (32 bits). Because the `ArrayBuffer` is 10 bytes long, there's no way to cleanly divide its contents into 4-byte chunks.

To fix this, create a typed array over a particular "slice" of the `ArrayBuffer`. The following `Uint32Array` only "views" the _first_ 8 bytes of the underlying `ArrayBuffer`: a `byteOffset` of `0` and a `length` of `2`, the number of `Uint32` values the array holds.

```ts
// 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
```

You don't need to create an `ArrayBuffer` instance first; pass a length to the typed array constructor instead:

```ts
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:

```ts
// 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);
```

Typed arrays provide the same methods as regular arrays, with a few exceptions. For example, `push` and `pop` are not available, because they would require resizing the underlying `ArrayBuffer`.

```ts
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
```

See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray) for more on typed array properties and methods.

### `Uint8Array`

`Uint8Array` is the most common typed array in JavaScript. It represents a classic "byte array": a sequence of 8-bit unsigned integers between 0 and 255.

In Bun, it has methods for converting between byte arrays and their base64 or hex string representations.

```ts
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]
```

It is the return value of [`TextEncoder#encode`](https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder), and the input type of [`TextDecoder#decode`](https://developer.mozilla.org/en-US/docs/Web/API/TextDecoder), two utility classes that translate between strings and various binary encodings, most notably `"utf-8"`.

```ts
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 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.

```ts
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
```

See the [Node.js documentation](https://nodejs.org/api/buffer.html).

## `Blob`

`Blob` is a Web API commonly used for representing files. It originated in browsers (unlike `ArrayBuffer`, which is part of JavaScript itself), but Node.js and Bun support it too.

You rarely create `Blob` instances directly; they usually come from an external source (like an `<input type="file">` element in the browser) or a library. That said, you can create a `Blob` from one or more string or binary "blob parts".

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

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

These parts can be `string`, `ArrayBuffer`, `TypedArray`, `DataView`, or other `Blob` instances. The parts are concatenated in the order they're given.

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

Read the contents of a `Blob` asynchronously in various formats.

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

### `BunFile`

`BunFile` is a subclass of `Blob` that represents 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.

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

### `File`

[`File`](https://developer.mozilla.org/en-US/docs/Web/API/File) is a subclass of `Blob` that adds a `name` and `lastModified` property. It's commonly used in the browser to represent files uploaded with an `<input type="file">` element. Node.js and Bun implement `File`.

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

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

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

See the [MDN documentation](https://developer.mozilla.org/en-US/docs/Web/API/Blob).

---

## Streams

Streams let you work with binary data without loading it all into memory at once. They're commonly used for reading and writing files, sending and receiving network requests, and processing large amounts of data.

Bun implements the Web APIs [`ReadableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream) and [`WritableStream`](https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream).

<Note>
  Bun also implements the `node:stream` module, including
  [`Readable`](https://nodejs.org/api/stream.html#stream_readable_streams),
  [`Writable`](https://nodejs.org/api/stream.html#stream_writable_streams), and
  [`Duplex`](https://nodejs.org/api/stream.html#stream_duplex_and_transform_streams). For complete documentation, refer
  to the Node.js docs.
</Note>

To create a readable stream:

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

Read the stream chunk-by-chunk with `for await`.

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

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

For more on streams in Bun, see [Streams](/runtime/streams).

---

## Conversion

Use this section as a reference for converting one binary format to another.

### From `ArrayBuffer`

Since `ArrayBuffer` stores the data that underlies other binary structures like `TypedArray`, the following snippets are not _converting_ from `ArrayBuffer` to another format. Instead, they _create_ a new instance using the underlying data.

#### To `TypedArray`

```ts
new Uint8Array(buf);
```

#### To `DataView`

```ts
new DataView(buf);
```

#### To `Buffer`

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

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

#### To `string`

As UTF-8:

```ts
new TextDecoder().decode(buf);
```

#### To `number[]`

```ts
Array.from(new Uint8Array(buf));
```

#### To `Blob`

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

#### To `ReadableStream`

The following snippet creates a `ReadableStream` and enqueues the entire `ArrayBuffer` as a single chunk.

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

<Accordion title="With chunking">
To stream the `ArrayBuffer` in chunks, use a `Uint8Array` view and enqueue each chunk.

```ts
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>

### From `TypedArray`

#### To `ArrayBuffer`

The `buffer` property is the underlying `ArrayBuffer`. A `TypedArray` can be a view of a _slice_ of that buffer, so the sizes may differ.

```ts
arr.buffer;
```

#### To `DataView`

To create a `DataView` over the same byte range as the `TypedArray`:

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

#### To `Buffer`

```ts
Buffer.from(arr);
```

#### To `string`

As UTF-8:

```ts
new TextDecoder().decode(arr);
```

#### To `number[]`

```ts
Array.from(arr);
```

#### To `Blob`

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

#### To `ReadableStream`

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

<Accordion title="With chunking">

To stream the `ArrayBuffer` in chunks, split the `TypedArray` into chunks and enqueue each one individually.

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

</Accordion>

### From `DataView`

#### To `ArrayBuffer`

```ts
view.buffer;
```

#### To `TypedArray`

Only works if the `byteLength` of the `DataView` is a multiple of the `BYTES_PER_ELEMENT` of the `TypedArray` subclass.

```ts
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...
```

#### To `Buffer`

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

#### To `string`

As UTF-8:

```ts
new TextDecoder().decode(view);
```

#### To `number[]`

```ts
Array.from(view);
```

#### To `Blob`

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

#### To `ReadableStream`

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

<Accordion title="With chunking">
To stream the `ArrayBuffer` in chunks, split the `DataView` into chunks and enqueue each one individually.

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

</Accordion>

### From `Buffer`

#### To `ArrayBuffer`

```ts
buf.buffer;
```

#### To `TypedArray`

```ts
new Uint8Array(buf);
```

#### To `DataView`

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

#### To `string`

As UTF-8:

```ts
buf.toString();
```

As base64:

```ts
buf.toString("base64");
```

As hex:

```ts
buf.toString("hex");
```

#### To `number[]`

```ts
Array.from(buf);
```

#### To `Blob`

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

#### To `ReadableStream`

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

<Accordion title="With chunking">
To stream the `ArrayBuffer` in chunks, split the `Buffer` into chunks and enqueue each one individually.

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

</Accordion>

### From `Blob`

#### To `ArrayBuffer`

```ts
await blob.arrayBuffer();
```

#### To `TypedArray`

```ts
await blob.bytes();
```

#### To `DataView`

```ts
new DataView(await blob.arrayBuffer());
```

#### To `Buffer`

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

#### To `string`

As UTF-8:

```ts
await blob.text();
```

#### To `number[]`

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

#### To `ReadableStream`

```ts
blob.stream();
```

### From `ReadableStream`

[`Response`](https://developer.mozilla.org/en-US/docs/Web/API/Response) is a common intermediate for converting a `ReadableStream` to other formats.

```ts
stream; // ReadableStream

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

But this approach is verbose and adds unnecessary overhead. Bun implements optimized convenience functions for converting a `ReadableStream` to various binary formats.

#### To `ArrayBuffer`

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

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

#### To `Uint8Array`

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

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

#### To `TypedArray`

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

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

#### To `DataView`

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

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

#### To `Buffer`

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

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

#### To `string`

As UTF-8:

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

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

#### To `number[]`

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

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

Bun provides a utility for resolving a `ReadableStream` to an array of its chunks. Each chunk may be a string, typed array, or `ArrayBuffer`.

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

#### To `Blob`

```ts
new Response(stream).blob();
```

#### To `ReadableStream`

To split a `ReadableStream` into two streams that can be consumed independently:

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