NOTE
Las APIs Bun.file y Bun.write documentadas en esta página están altamente optimizadas y representan la forma recomendada de realizar tareas de sistema de archivos usando Bun. Para operaciones que aún no están disponibles con Bun.file, como mkdir o readdir, puedes usar la implementación casi completa de Bun del módulo node:fs.
Leer archivos (Bun.file())
Bun.file(path): BunFile
Crea una instancia BunFile con la función Bun.file(path). Un BunFile representa un archivo cargado perezosamente; inicializarlo no lee realmente el archivo del disco.
const foo = Bun.file("foo.txt"); // relativo a cwd
foo.size; // número de bytes
foo.type; // tipo MIMELa referencia sigue la interfaz Blob, por lo que el contenido se puede leer en varios formatos.
const foo = Bun.file("foo.txt");
await foo.text(); // contenido como cadena
await foo.json(); // contenido como objeto JSON
await foo.stream(); // contenido como ReadableStream
await foo.arrayBuffer(); // contenido como ArrayBuffer
await foo.bytes(); // contenido como Uint8ArrayLas referencias a archivos también se pueden crear usando descriptores de archivo numéricos o URLs file://.
Bun.file(1234);
Bun.file(new URL(import.meta.url)); // referencia al archivo actualUn BunFile puede apuntar a una ubicación en disco donde no existe un archivo.
const notreal = Bun.file("notreal.txt");
notreal.size; // 0
notreal.type; // "text/plain;charset=utf-8"
const exists = await notreal.exists(); // falseEl tipo MIME predeterminado es text/plain;charset=utf-8, pero se puede anular pasando un segundo argumento a Bun.file.
const notreal = Bun.file("notreal.json", { type: "application/json" });
notreal.type; // => "application/json;charset=utf-8"Por conveniencia, Bun expone stdin, stdout y stderr como instancias de BunFile.
Bun.stdin; // solo lectura
Bun.stdout;
Bun.stderr;Eliminar archivos (file.delete())
Puedes eliminar un archivo llamando a la función .delete().
await Bun.file("logs.json").delete();Escribir archivos (Bun.write())
Bun.write(destination, data): Promise<number>
La función Bun.write es una multi-herramienta para escribir payloads de todo tipo en disco.
El primer argumento es el destination (destino) que puede tener cualquiera de los siguientes tipos:
string: Una ruta a una ubicación en el sistema de archivos. Usa el módulo"path"para manipular rutas.URL: Un descriptorfile://.BunFile: Una referencia a archivo.
El segundo argumento son los datos a escribir. Puede ser cualquiera de los siguientes:
stringBlob(incluyendoBunFile)ArrayBufferoSharedArrayBufferTypedArray(Uint8Array, etc.)Response
Todas las permutaciones posibles se manejan usando las llamadas al sistema más rápidas disponibles en la plataforma actual.
Ver llamadas al sistema
| Salida | Entrada | Llamada al sistema | Plataforma |
|---|---|---|---|
| archivo | archivo | copy_file_range | Linux |
| archivo | pipe | sendfile | Linux |
| pipe | pipe | splice | Linux |
| terminal | archivo | sendfile | Linux |
| terminal | terminal | sendfile | Linux |
| socket | archivo o pipe | sendfile (si http, no https) | Linux |
| archivo (no existe) | archivo (ruta) | clonefile | macOS |
| archivo (existe) | archivo | fcopyfile | macOS |
| archivo | Blob o cadena | write | macOS |
| archivo | Blob o cadena | write | Linux |
Para escribir una cadena en disco:
const data = `Era el mejor de los tiempos, era el peor de los tiempos.`;
await Bun.write("output.txt", data);Para copiar un archivo a otra ubicación en disco:
const input = Bun.file("input.txt");
const output = Bun.file("output.txt"); // ¡aún no existe!
await Bun.write(output, input);Para escribir un array de bytes en disco:
const encoder = new TextEncoder();
const data = encoder.encode("datadatadata"); // Uint8Array
await Bun.write("output.txt", data);Para escribir un archivo en stdout:
const input = Bun.file("input.txt");
await Bun.write(Bun.stdout, input);Para escribir el cuerpo de una respuesta HTTP en disco:
const response = await fetch("https://bun.com");
await Bun.write("index.html", response);Escritura incremental con FileSink
Bun proporciona una API nativa de escritura incremental de archivos llamada FileSink. Para obtener una instancia FileSink desde un BunFile:
const file = Bun.file("output.txt");
const writer = file.writer();Para escribir incrementalmente en el archivo, llama a .write().
const file = Bun.file("output.txt");
const writer = file.writer();
writer.write("era el mejor de los tiempos\n");
writer.write("era el peor de los tiempos\n");Estos fragmentos se almacenarán en búfer internamente. Para vaciar el búfer a disco, usa .flush(). Esto devuelve el número de bytes vaciados.
writer.flush(); // escribe el búfer a discoEl búfer también se vaciará automáticamente cuando se alcance la marca de agua alta del FileSink; es decir, cuando su búfer interno esté lleno. Este valor se puede configurar.
const file = Bun.file("output.txt");
const writer = file.writer({ highWaterMark: 1024 * 1024 }); // 1MBPara vaciar el búfer y cerrar el archivo:
writer.end();Ten en cuenta que, por defecto, el proceso bun permanecerá activo hasta que este FileSink se cierre explícitamente con .end(). Para optar por no participar en este comportamiento, puedes "desreferenciar" la instancia.
writer.unref();
// para "volver a referenciarlo" más tarde
writer.ref();Directorios
La implementación de node:fs de Bun es rápida, y aún no hemos implementado una API específica de Bun para leer directorios. Por ahora, debes usar node:fs para trabajar con directorios en Bun.
Leer directorios (readdir)
Para leer un directorio en Bun, usa readdir de node:fs.
import { readdir } from "node:fs/promises";
// lee todos los archivos en el directorio actual
const files = await readdir(import.meta.dir);Leer directorios recursivamente
Para leer un directorio recursivamente en Bun, usa readdir con recursive: true.
import { readdir } from "node:fs/promises";
// lee todos los archivos en el directorio actual, recursivamente
const files = await readdir("../", { recursive: true });Crear directorios (mkdir)
Para crear un directorio recursivamente, usa mkdir en node:fs:
import { mkdir } from "node:fs/promises";
await mkdir("path/to/dir", { recursive: true });Benchmarks
La siguiente es una implementación de 3 líneas del comando cat de Linux.
// Uso
// bun ./cat.ts ./ruta-al-archivo
import { resolve } from "path";
const path = resolve(process.argv.at(-1));
await Bun.write(Bun.stdout, Bun.file(path));Para ejecutar el archivo:
bun ./cat.ts ./ruta-al-archivoSe ejecuta 2 veces más rápido que GNU cat para archivos grandes en Linux.
Referencia
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;
}