Skip to content

Bun File I/O

Bun provides high-performance file I/O APIs that are faster and easier to use than Node.js's fs module. This chapter introduces Bun's file operations.

Bun.file() API

Creating File References

typescript
// Create file reference (does not read immediately)
const file = Bun.file("./data.txt");

// File information
console.log(file.name);    // File path
console.log(file.size);    // File size (bytes)
console.log(file.type);    // MIME type

Reading File Content

typescript
const file = Bun.file("./data.txt");

// Read as text
const text = await file.text();
console.log(text);

// Read as JSON
const jsonFile = Bun.file("./config.json");
const config = await jsonFile.json();
console.log(config);

// Read as ArrayBuffer
const buffer = await file.arrayBuffer();

// Read as Blob
const blob = await file.blob();

// Read as Uint8Array
const bytes = await file.bytes();

Checking if File Exists

typescript
const file = Bun.file("./maybe-exists.txt");

// Check if file exists
const exists = await file.exists();
console.log(exists ? "File exists" : "File does not exist");

Writing Files

Bun.write()

typescript
// Write text
await Bun.write("./output.txt", "Hello, Bun!");

// Write JSON
await Bun.write("./data.json", JSON.stringify({ name: "Bun" }, null, 2));

// Write binary data
const bytes = new Uint8Array([72, 101, 108, 108, 111]);
await Bun.write("./binary.bin", bytes);

// Write Response object
const response = await fetch("https://example.com/image.png");
await Bun.write("./image.png", response);

// Write Blob
const blob = new Blob(["Hello World"], { type: "text/plain" });
await Bun.write("./blob.txt", blob);

Write Options

typescript
// Append mode
const writer = Bun.file("./log.txt").writer();
writer.write("First line\n");
writer.write("Second line\n");
await writer.end();

Streaming Read/Write

Read Stream

typescript
const file = Bun.file("./large-file.txt");

// Get readable stream
const stream = file.stream();

// Use for await to read chunks
for await (const chunk of stream) {
  console.log("Read chunk:", chunk.length, "bytes");
}

Write Stream

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

// Write data
writer.write("First line\n");
writer.write("Second line\n");
writer.write(new Uint8Array([65, 66, 67]));

// Complete writing
await writer.end();

Pipe Operations

typescript
// Copy from one file to another
const source = Bun.file("./source.txt");
const dest = Bun.file("./dest.txt");

await Bun.write(dest, source);

Directory Operations

Reading Directories

typescript
import { readdir, readdirSync } from "node:fs/promises";

// Read directory asynchronously
const files = await readdir("./src");
console.log(files);

// Include file type information
const entries = await readdir("./src", { withFileTypes: true });
for (const entry of entries) {
  console.log(
    entry.name,
    entry.isDirectory() ? "directory" : "file"
  );
}

Using Bun's Glob

typescript
// Use glob to match files
const glob = new Bun.Glob("**/*.ts");

// Iterate over matched files
for await (const file of glob.scan("./src")) {
  console.log(file);
}

// Get all matched files
const files = await Array.fromAsync(glob.scan("./src"));
console.log(files);

Creating Directories

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

// Create directory
await mkdir("./new-folder");

// Create recursively
await mkdir("./a/b/c", { recursive: true });

Deleting Directories

typescript
import { rmdir, rm } from "node:fs/promises";

// Delete empty directory
await rmdir("./empty-folder");

// Recursive delete (includes contents)
await rm("./folder-with-content", { recursive: true });

File Information

Getting File Status

typescript
import { stat, lstat } from "node:fs/promises";

const stats = await stat("./file.txt");

console.log({
  size: stats.size,
  isFile: stats.isFile(),
  isDirectory: stats.isDirectory(),
  isSymbolicLink: stats.isSymbolicLink(),
  createdTime: stats.birthtime,
  modifiedTime: stats.mtime,
  accessTime: stats.atime,
});

Using Bun.file() to Get Information

typescript
const file = Bun.file("./file.txt");

console.log({
  path: file.name,
  size: file.size,
  type: file.type,
  lastModified: file.lastModified,
});

File Path Operations

path Module

typescript
import path from "node:path";

// Join paths
const fullPath = path.join("./src", "utils", "helper.ts");
// "./src/utils/helper.ts"

// Resolve to absolute path
const absolute = path.resolve("./file.txt");
// "/Users/xxx/project/file.txt"

// Get directory name
const dir = path.dirname("/path/to/file.txt");
// "/path/to"

// Get base name
const base = path.basename("/path/to/file.txt");
// "file.txt"

// Get extension
const ext = path.extname("/path/to/file.txt");
// ".txt"

// Parse path
const parsed = path.parse("/path/to/file.txt");
// { root: '/', dir: '/path/to', base: 'file.txt', ext: '.txt', name: 'file' }

Special Paths

typescript
// Current working directory
console.log(process.cwd());

// Current file directory
console.log(import.meta.dir);

// Current file path
console.log(import.meta.path);

// Main module directory
console.log(Bun.main);

File Copy and Move

Copying Files

typescript
import { copyFile } from "node:fs/promises";

// Use Node.js API
await copyFile("./source.txt", "./dest.txt");

// Use Bun.write
const source = Bun.file("./source.txt");
await Bun.write("./dest.txt", source);

Moving/Renaming Files

typescript
import { rename } from "node:fs/promises";

// Rename
await rename("./old-name.txt", "./new-name.txt");

// Move file
await rename("./file.txt", "./folder/file.txt");

Temporary Files

Creating Temporary Files

typescript
import { tmpdir } from "node:os";
import path from "node:path";

// Get temp directory
const tempDir = tmpdir();

// Create temp file
const tempFile = path.join(tempDir, `temp-${Date.now()}.txt`);
await Bun.write(tempFile, "temporary content");

console.log("Temp file:", tempFile);

Using Bun Temporary Files

typescript
// Bun automatically creates temp file
const tempFile = Bun.file("/tmp/my-temp-file.txt");
await Bun.write(tempFile, "temporary data");

Watching File Changes

Using Bun.watch (Experimental)

typescript
import { watch } from "node:fs";

// Watch for file changes
const watcher = watch("./src", { recursive: true }, (event, filename) => {
  console.log(`File ${filename} triggered ${event} event`);
});

// Stop watching
// watcher.close();

Practical Application

typescript
// Watch config file changes and reload
import { watch } from "node:fs";

let config = await loadConfig();

watch("./config.json", async (event) => {
  if (event === "change") {
    console.log("Config file changed, reloading...");
    config = await loadConfig();
  }
});

async function loadConfig() {
  return Bun.file("./config.json").json();
}

Practical Examples

Logger

typescript
// logger.ts
class Logger {
  private logFile: string;
  private writer: ReturnType<typeof Bun.file.prototype.writer> | null = null;

  constructor(logFile: string) {
    this.logFile = logFile;
  }

  private async getWriter() {
    if (!this.writer) {
      this.writer = Bun.file(this.logFile).writer();
    }
    return this.writer;
  }

  async log(level: string, message: string) {
    const timestamp = new Date().toISOString();
    const line = `[${timestamp}] [${level}] ${message}\n`;
    
    const writer = await this.getWriter();
    writer.write(line);
    
    // Also output to console
    console.log(line.trim());
  }

  async info(message: string) {
    await this.log("INFO", message);
  }

  async error(message: string) {
    await this.log("ERROR", message);
  }

  async close() {
    if (this.writer) {
      await this.writer.end();
      this.writer = null;
    }
  }
}

// Usage
const logger = new Logger("./app.log");
await logger.info("Application started");
await logger.error("An error occurred");
await logger.close();

File Upload Handling

typescript
// upload-server.ts
const server = Bun.serve({
  port: 3000,
  
  async fetch(request) {
    if (request.method === "POST" && request.url.endsWith("/upload")) {
      const formData = await request.formData();
      const file = formData.get("file") as File;
      
      if (!file) {
        return new Response("No file uploaded", { status: 400 });
      }
      
      // Save file
      const savePath = `./uploads/${file.name}`;
      await Bun.write(savePath, file);
      
      return Response.json({
        message: "Upload successful",
        filename: file.name,
        size: file.size,
      });
    }
    
    return new Response("Upload endpoint: POST /upload", { status: 200 });
  },
});

console.log(`Upload server running at http://localhost:${server.port}`);

Config File Management

typescript
// config-manager.ts
class ConfigManager<T> {
  private configPath: string;
  private cache: T | null = null;

  constructor(configPath: string) {
    this.configPath = configPath;
  }

  async load(): Promise<T> {
    if (this.cache) return this.cache;
    
    const file = Bun.file(this.configPath);
    if (!(await file.exists())) {
      throw new Error(`Config file not found: ${this.configPath}`);
    }
    
    this.cache = await file.json();
    return this.cache!;
  }

  async save(config: T): Promise<void> {
    await Bun.write(
      this.configPath,
      JSON.stringify(config, null, 2)
    );
    this.cache = config;
  }

  async update(updates: Partial<T>): Promise<T> {
    const current = await this.load();
    const updated = { ...current, ...updates };
    await this.save(updated);
    return updated;
  }

  invalidateCache(): void {
    this.cache = null;
  }
}

// Usage
interface AppConfig {
  port: number;
  debug: boolean;
  apiKey: string;
}

const configManager = new ConfigManager<AppConfig>("./config.json");
const config = await configManager.load();
console.log("Current config:", config);

await configManager.update({ debug: true });

Performance Comparison

Bun file I/O is much faster than Node.js:

Reading 1MB file:
Node.js fs.readFile:  5ms
Bun.file().text():    1ms

Writing 1MB file:
Node.js fs.writeFile: 10ms
Bun.write():          2ms

Summary

This chapter covered:

  • ✅ Bun.file() and Bun.write() APIs
  • ✅ Streaming read/write for large files
  • ✅ Directory operations and glob matching
  • ✅ File information and path operations
  • ✅ File watching and temporary files
  • ✅ Practical examples

Next Steps

Continue reading HTTP Server to learn how to create high-performance web servers with Bun.

Content is for learning and research only.