Skip to content

NOTE

このページで文書化されている Bun.file および Bun.write API は非常に最適化されており、Bun を使用してファイルシステムタスクを実行する推奨される方法を表しています。mkdirreaddir など、Bun.file でまだ利用できない操作については、Bun の ほぼ完全な node:fs モジュールの実装を使用できます。


ファイルの読み取り(Bun.file()

Bun.file(path): BunFile

Bun.file(path) 関数で BunFile インスタンスを作成します。BunFile は遅延読み込みされるファイルを表します。初期化しても実際にディスクからファイルが読み込まれるわけではありません。

ts
const foo = Bun.file("foo.txt"); // cwd からの相対パス
foo.size; // バイト数
foo.type; // MIME タイプ

参照は Blob インターフェースに準拠しているため、さまざまな形式で内容を読み取ることができます。

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

await foo.text(); // 内容を文字列として
await foo.json(); // 内容を JSON オブジェクトとして
await foo.stream(); // 内容を ReadableStream として
await foo.arrayBuffer(); // 内容を ArrayBuffer として
await foo.bytes(); // 内容を Uint8Array として

ファイル参照は、数値の ファイルディスクリプター または file:// URL を使用して作成することもできます。

ts
Bun.file(1234);
Bun.file(new URL(import.meta.url)); // 現在のファイルへの参照

BunFile はファイルが存在しないディスク上の場所を指すことができます。

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

デフォルトの MIME タイプは text/plain;charset=utf-8 ですが、Bun.file に第 2 引数を渡すことでオーバーライドできます。

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

便宜上、Bun は stdinstdoutstderrBunFile のインスタンスとして公開しています。

ts
Bun.stdin; // 読み取り専用
Bun.stdout;
Bun.stderr;

ファイルの削除(file.delete()

.delete() 関数を呼び出すことでファイルを削除できます。

ts
await Bun.file("logs.json").delete();

ファイルの書き込み(Bun.write()

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

Bun.write 関数は、あらゆる種類のペイロードをディスクに書き込むためのマルチツールです。

第 1 引数は destination で、以下のいずれかの型を持つことができます。

  • string: ファイルシステム上のパス。パスの操作には "path" モジュールを使用します。
  • URL: file:// 記述子。
  • BunFile: ファイル参照。

第 2 引数は書き込まれるデータです。以下のいずれかになります。

  • string
  • BlobBunFile を含む)
  • ArrayBuffer または SharedArrayBuffer
  • TypedArrayUint8Array など)
  • Response

すべての可能な組み合わせは、現在のプラットフォームで利用可能な最速のシステムコールを使用して処理されます。

システムコールの表示

出力入力システムコールプラットフォーム
filefilecopy_file_rangeLinux
filepipesendfileLinux
pipepipespliceLinux
terminalfilesendfileLinux
terminalterminalsendfileLinux
socketfile or pipesendfile (http の場合、https は除く)Linux
file (存在しない)file (path)clonefilemacOS
file (存在する)filefcopyfilemacOS
fileBlob or stringwritemacOS
fileBlob or stringwriteLinux

文字列をディスクに書き込むには:

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

ファイルをディスク上の別の場所にコピーするには:

ts
const input = Bun.file("input.txt");
const output = Bun.file("output.txt"); // まだ存在しない!
await Bun.write(output, input);

バイト配列をディスクに書き込むには:

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

ファイルを stdout に書き込むには:

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

HTTP レスポンスの本文をディスクに書き込むには:

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

FileSink を使用した増分書き込み

Bun は FileSink と呼ばれるネイティブな増分ファイル書き込み API を提供します。BunFile から FileSink インスタンスを取得するには:

ts
const file = Bun.file("output.txt");
const writer = file.writer();

ファイルに増分的に書き込むには、.write() を呼び出します。

ts
const file = Bun.file("output.txt");
const writer = file.writer();

writer.write("it was the best of times\n");
writer.write("it was the worst of times\n");

これらのチャンクは内部的にバッファリングされます。バッファをディスクにフラッシュするには、.flush() を使用します。これはフラッシュされたバイト数を返します。

ts
writer.flush(); // バッファをディスクに書き込む

バッファは、FileSinkハイウォーターマーク に達したとき、つまり内部バッファがいっぱいになったときにも自動的にフラッシュされます。この値は構成できます。

ts
const file = Bun.file("output.txt");
const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MB

バッファをフラッシュしてファイルを閉じるには:

ts
writer.end();

デフォルトでは、bun プロセスはこの FileSink.end() で明示的に閉じられるまで生存し続けることに注意してください。この動作をオプトアウトするには、インスタンスを "unref" できます。

ts
writer.unref();

// 後で "re-ref" するには
writer.ref();

ディレクトリ

Bun の node:fs の実装は高速ですが、ディレクトリの読み取りのための Bun 固有の API はまだ実装されていません。現時点では、Bun でディレクトリを操作するには node:fs を使用する必要があります。

ディレクトリの読み取り(readdir)

Bun でディレクトリを読み取るには、node:fs から readdir を使用します。

ts
import { readdir } from "node:fs/promises";

// 現在のディレクトリのすべてのファイルを読み取る
const files = await readdir(import.meta.dir);

再帰的にディレクトリを読み取る

Bun でディレクトリを再帰的に読み取るには、recursive: truereaddir を使用します。

ts
import { readdir } from "node:fs/promises";

// 現在のディレクトリのすべてのファイルを再帰的に読み取る
const files = await readdir("../", { recursive: true });

ディレクトリの作成(mkdir)

ディレクトリを再帰的に作成するには、node:fsmkdir を使用します。

ts
import { mkdir } from "node:fs/promises";

await mkdir("path/to/dir", { recursive: true });

ベンチマーク

以下は Linux の cat コマンドの 3 行実装です。

ts
// 使用方法
// 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));

ファイルを実行するには:

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

これは、Linux で大きなファイルの場合、GNU cat よりも 2 倍高速に実行されます。


リファレンス

ts
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(): ReadableStream;
  arrayBuffer(): Promise<ArrayBuffer>;
  json(): Promise<any>;
  writer(params: { highWaterMark?: number }): FileSink;
  exists(): Promise<boolean>;
}

export interface FileSink {
  write(chunk: string | ArrayBufferView | ArrayBuffer | SharedArrayBuffer): number;
  flush(): number | Promise<number>;
  end(error?: Error): number | Promise<number>;
  start(options?: { highWaterMark?: number }): void;
  ref(): void;
  unref(): void;
}

Bun by www.bunjs.com.cn 編集