Skip to content

NOTE

本頁文檔介紹的 Bun.fileBun.write API 經過高度優化,代表使用 Bun 執行文件系統任務的推薦方式。對於 Bun.file 尚未支持的操作(如 mkdirreaddir),你可以使用 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 傳遞第二個參數來覆蓋。

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

為方便起見,Bun 將 stdinstdoutstderr 公開為 BunFile 實例。

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 函數是一個多用途工具,用於將各種有效負載寫入磁盤。

第一個參數是 destination,可以是以下任何類型:

  • string:文件系統上的路徑。使用 "path" 模塊來操作路徑。
  • URLfile:// 描述符。
  • BunFile:文件引用。

第二個參數是要寫入的數據。可以是以下任何內容:

  • string
  • Blob(包括 BunFile
  • ArrayBufferSharedArrayBuffer
  • TypedArrayUint8Array 等)
  • Response

所有可能的排列都使用當前平台上最快的可用系統調用處理。

系統調用

輸出輸入系統調用平台
filefilecopy_file_rangeLinux
filepipesendfileLinux
pipepipespliceLinux
terminalfilesendfileLinux
terminalterminalsendfileLinux
socketfile 或 pipesendfile(如果是 http,不是 https)Linux
file(不存在)file(路徑)clonefilemacOS
file(存在)filefcopyfilemacOS
fileBlob 或 stringwritemacOS
fileBlob 或 stringwriteLinux

要將字符串寫入磁盤:

ts
const data = `這是最好的時代,這是最壞的時代。`;
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("這是最好的時代\n");
writer.write("這是最壞的時代\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:fs 中的 mkdir

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學習網由www.bunjs.com.cn整理維護