Skip to content

NOTE

이 페이지에 문서화된 Bun.fileBun.write API 는 고도로 최적화되었으며 Bun 을 사용하여 파일 시스템 작업을 수행하는 권장 방법입니다. mkdir 이나 readdir 과 같이 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 에 두 번째 인수를 전달하여 재정의할 수 있습니다.

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

편의상 Bun 은 stdin, stdout, stderrBunFile 인스턴스로 노출합니다.

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" 모듈을 사용합니다.
  • URL: file:// 디스크립터.
  • BunFile: 파일 레퍼런스.

두 번째 인수는 쓸 데이터입니다. 다음 중 하나일 수 있습니다:

  • string
  • Blob (BunFile 포함)
  • ArrayBuffer 또는 SharedArrayBuffer
  • TypedArray (Uint8Array 등)
  • 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 = `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(); // 버퍼를 디스크에 쓰기

버퍼는 FileSinkhigh water mark 에 도달했을 때, 즉 내부 버퍼가 가득 찼을 때 자동으로 플러시됩니다. 이 값은 설정할 수 있습니다.

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

버퍼를 플러시하고 파일을 닫으려면:

ts
writer.end();

기본적으로 bun 프로세스는 이 FileSink.end() 로 명시적으로 닫힐 때까지 살아있습니다. 이 동작을 opt-out 하려면 인스턴스를 "unref"할 수 있습니다.

ts
writer.unref();

// 나중에 "re-ref"
writer.ref();

디렉토리

Bun 의 node:fs 구현은 빠르며 아직 디렉토리 읽기를 위한 Bun 특정 API 를 구현하지 않았습니다. 당분간은 Bun 에서 디렉토리를 작업할 때 node:fs 를 사용해야 합니다.

디렉토리 읽기 (readdir)

Bun 에서 디렉토리를 읽으려면 node:fsreaddir 을 사용합니다.

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

// 현재 디렉토리의 모든 파일 읽기
const files = await readdir(import.meta.dir);

재귀적으로 디렉토리 읽기

Bun 에서 디렉토리를 재귀적으로 읽으려면 recursive: true 와 함께 readdir 을 사용합니다.

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 편집