Skip to content

Latest commit

 

History

History
254 lines (177 loc) · 5.29 KB

file-io.md

File metadata and controls

254 lines (177 loc) · 5.29 KB

{% callout %}

Note — The Bun.file and Bun.write APIs documented on this page are heavily optimized and represent the recommended way to perform file-system tasks using Bun. For operations that are not yet available with Bun.file, such as mkdir, you can use Bun's nearly complete implementation of the node:fs module.

{% /callout %}

Bun provides a set of optimized APIs for reading and writing files.

Reading files (Bun.file())

Bun.file(path): BunFile

Create a BunFile instance with the Bun.file(path) function. A BunFile represents a lazily-loaded file; initializing it does not actually read the file from disk.

const foo = Bun.file("foo.txt"); // relative to cwd
foo.size; // number of bytes
foo.type; // MIME type

The reference conforms to the Blob interface, so the contents can be read in various formats.

const foo = Bun.file("foo.txt");

await foo.text(); // contents as a string
await foo.stream(); // contents as ReadableStream
await foo.arrayBuffer(); // contents as ArrayBuffer

File references can also be created using numerical file descriptors or file:// URLs.

Bun.file(1234);
Bun.file(new URL(import.meta.url)); // reference to the current file

A BunFile can point to a location on disk where a file does not exist.

const notreal = Bun.file("notreal.txt");
notreal.size; // 0
notreal.type; // "text/plain;charset=utf-8"

The default MIME type is text/plain;charset=utf-8, but it can be overridden by passing a second argument to Bun.file.

const notreal = Bun.file("notreal.json", { type: "application/json" });
notreal.type; // => "application/json;charset=utf-8"

For convenience, Bun exposes stdin, stdout and stderr as instances of BunFile.

Bun.stdin; // readonly
Bun.stdout;
Bun.stderr;

Writing files (Bun.write())

Bun.write(destination, data): Promise<number>

The Bun.write function is a multi-tool for writing payloads of all kinds to disk.

The first argument is the destination which can have any of the following types:

  • string: A path to a location on the file system. Use the "path" module to manipulate paths.
  • URL: A file:// descriptor.
  • BunFile: A file reference.

The second argument is the data to be written. It can be any of the following:

  • string
  • Blob (including BunFile)
  • ArrayBuffer or SharedArrayBuffer
  • TypedArray (Uint8Array, et. al.)
  • Response

All possible permutations are handled using the fastest available system calls on the current platform.

{% details summary="See syscalls" %}

{% table %}

  • Output
  • Input
  • System call
  • Platform

  • file
  • file
  • copy_file_range
  • Linux

  • file
  • pipe
  • sendfile
  • Linux

  • pipe
  • pipe
  • splice
  • Linux

  • terminal
  • file
  • sendfile
  • Linux

  • terminal
  • terminal
  • sendfile
  • Linux

  • socket
  • file or pipe
  • sendfile (if http, not https)
  • Linux

  • file (doesn't exist)
  • file (path)
  • clonefile
  • macOS

  • file (exists)
  • file
  • fcopyfile
  • macOS

  • file
  • Blob or string
  • write
  • macOS

  • file
  • Blob or string
  • write
  • Linux

{% /table %}

{% /details %}

To write a string to disk:

const data = `It was the best of times, it was the worst of times.`;
await Bun.write("output.txt", data);

To copy a file to another location on disk:

const input = Bun.file("input.txt");
const output = Bun.file("output.txt"); // doesn't exist yet!
await Bun.write(output, input);

To write a byte array to disk:

const encoder = new TextEncoder();
const data = encoder.encode("datadatadata"); // Uint8Array
await Bun.write("output.txt", data);

To write a file to stdout:

const input = Bun.file("input.txt");
await Bun.write(Bun.stdout, input);

To write an HTTP response to disk:

const response = await fetch("https://bun.sh");
await Bun.write("index.html", response);

Benchmarks

The following is a 3-line implementation of the Linux cat command.

// Usage
// $ bun ./cat.ts ./path-to-file

import { resolve } from "path";

const path = resolve(process.argv.at(-1));
await Bun.write(Bun.stdout, Bun.file(path));

To run the file:

$ bun ./cat.ts ./path-to-file

It runs 2x faster than GNU cat for large files on Linux.

{% image src="/images/cat.jpg" /%}

Reference

interface Bun {
  stdin: BunFile;
  stdout: BunFile;
  stderr: BunFile;

  file(path: string | number | URL, options?: { type?: string }): BunFile;

  write(
    destination: string | number | BunFile | URL,
    input: string | Blob | ArrayBuffer | SharedArrayBuffer | TypedArray | Response,
  ): Promise<number>;
}

interface BunFile {
  readonly size: number;
  readonly type: string;

  text(): Promise<string>;
  stream(): Promise<ReadableStream>;
  arrayBuffer(): Promise<ArrayBuffer>;
  json(): Promise<any>;
}