NOTE
このページで文書化されている Bun.file および Bun.write API は非常に最適化されており、Bun を使用してファイルシステムタスクを実行する推奨される方法を表しています。mkdir や readdir など、Bun.file でまだ利用できない操作については、Bun の ほぼ完全な node:fs モジュールの実装を使用できます。
ファイルの読み取り(Bun.file())
Bun.file(path): BunFile
Bun.file(path) 関数で BunFile インスタンスを作成します。BunFile は遅延読み込みされるファイルを表します。初期化しても実際にディスクからファイルが読み込まれるわけではありません。
const foo = Bun.file("foo.txt"); // cwd からの相対パス
foo.size; // バイト数
foo.type; // MIME タイプ参照は Blob インターフェースに準拠しているため、さまざまな形式で内容を読み取ることができます。
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 を使用して作成することもできます。
Bun.file(1234);
Bun.file(new URL(import.meta.url)); // 現在のファイルへの参照BunFile はファイルが存在しないディスク上の場所を指すことができます。
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 引数を渡すことでオーバーライドできます。
const notreal = Bun.file("notreal.json", { type: "application/json" });
notreal.type; // => "application/json;charset=utf-8"便宜上、Bun は stdin、stdout、stderr を BunFile のインスタンスとして公開しています。
Bun.stdin; // 読み取り専用
Bun.stdout;
Bun.stderr;ファイルの削除(file.delete())
.delete() 関数を呼び出すことでファイルを削除できます。
await Bun.file("logs.json").delete();ファイルの書き込み(Bun.write())
Bun.write(destination, data): Promise<number>
Bun.write 関数は、あらゆる種類のペイロードをディスクに書き込むためのマルチツールです。
第 1 引数は destination で、以下のいずれかの型を持つことができます。
string: ファイルシステム上のパス。パスの操作には"path"モジュールを使用します。URL:file://記述子。BunFile: ファイル参照。
第 2 引数は書き込まれるデータです。以下のいずれかになります。
stringBlob(BunFileを含む)ArrayBufferまたはSharedArrayBufferTypedArray(Uint8Arrayなど)Response
すべての可能な組み合わせは、現在のプラットフォームで利用可能な最速のシステムコールを使用して処理されます。
システムコールの表示
| 出力 | 入力 | システムコール | プラットフォーム |
|---|---|---|---|
| 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 (http の場合、https は除く) | Linux |
| file (存在しない) | file (path) | clonefile | macOS |
| file (存在する) | file | fcopyfile | macOS |
| file | Blob or string | write | macOS |
| file | Blob or string | write | Linux |
文字列をディスクに書き込むには:
const data = `It was the best of times, it was the worst of times.`;
await Bun.write("output.txt", data);ファイルをディスク上の別の場所にコピーするには:
const input = Bun.file("input.txt");
const output = Bun.file("output.txt"); // まだ存在しない!
await Bun.write(output, input);バイト配列をディスクに書き込むには:
const encoder = new TextEncoder();
const data = encoder.encode("datadatadata"); // Uint8Array
await Bun.write("output.txt", data);ファイルを stdout に書き込むには:
const input = Bun.file("input.txt");
await Bun.write(Bun.stdout, input);HTTP レスポンスの本文をディスクに書き込むには:
const response = await fetch("https://bun.com");
await Bun.write("index.html", response);FileSink を使用した増分書き込み
Bun は FileSink と呼ばれるネイティブな増分ファイル書き込み API を提供します。BunFile から FileSink インスタンスを取得するには:
const file = Bun.file("output.txt");
const writer = file.writer();ファイルに増分的に書き込むには、.write() を呼び出します。
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() を使用します。これはフラッシュされたバイト数を返します。
writer.flush(); // バッファをディスクに書き込むバッファは、FileSink の ハイウォーターマーク に達したとき、つまり内部バッファがいっぱいになったときにも自動的にフラッシュされます。この値は構成できます。
const file = Bun.file("output.txt");
const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MBバッファをフラッシュしてファイルを閉じるには:
writer.end();デフォルトでは、bun プロセスはこの FileSink が .end() で明示的に閉じられるまで生存し続けることに注意してください。この動作をオプトアウトするには、インスタンスを "unref" できます。
writer.unref();
// 後で "re-ref" するには
writer.ref();ディレクトリ
Bun の node:fs の実装は高速ですが、ディレクトリの読み取りのための Bun 固有の API はまだ実装されていません。現時点では、Bun でディレクトリを操作するには node:fs を使用する必要があります。
ディレクトリの読み取り(readdir)
Bun でディレクトリを読み取るには、node:fs から readdir を使用します。
import { readdir } from "node:fs/promises";
// 現在のディレクトリのすべてのファイルを読み取る
const files = await readdir(import.meta.dir);再帰的にディレクトリを読み取る
Bun でディレクトリを再帰的に読み取るには、recursive: true で readdir を使用します。
import { readdir } from "node:fs/promises";
// 現在のディレクトリのすべてのファイルを再帰的に読み取る
const files = await readdir("../", { recursive: true });ディレクトリの作成(mkdir)
ディレクトリを再帰的に作成するには、node:fs の mkdir を使用します。
import { mkdir } from "node:fs/promises";
await mkdir("path/to/dir", { recursive: true });ベンチマーク
以下は Linux の cat コマンドの 3 行実装です。
// 使用方法
// 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));ファイルを実行するには:
bun ./cat.ts ./path-to-fileこれは、Linux で大きなファイルの場合、GNU cat よりも 2 倍高速に実行されます。
リファレンス
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;
}