# How to Perform File System Operations Using Bun.file in Bun

> Learn to perform file system operations like reading and writing files using Bun.file and Bun.write in Bun. Discover async methods for streamlined file handling.

- Repository: [Bun/bun](https://github.com/oven-sh/bun)
- Tags: how-to-guide
- Published: 2026-02-28

---

**`Bun.file`** creates a `BunFile` object—a subclass of the standard `Blob`—that provides async methods for reading, streaming, and inspecting files, while `Bun.write()` and the `writer()` handle writing operations.

`Bun.file` is the primary API for file-system operations in the Bun runtime (`oven-sh/bun`). It accepts a file path, URL, buffer, or file descriptor and returns a `BunFile` instance that integrates seamlessly with Web APIs like Fetch and FormData. Because `BunFile` inherits from `Blob`, it works natively with `new Response(Bun.file(...))` and other web-compatible interfaces.

## Understanding the BunFile Interface

The `BunFile` interface extends the standard `Blob` class and adds file-system-specific methods. According to the type definitions in [`packages/bun-types/bun.d.ts`](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts) [[line 3998]](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts#L3998), the interface includes properties like `size` and methods such as `stat()`, `exists()`, and `unlink()` [[lines 2036-2080]](https://github.com/oven-sh/bun/blob/main/packages/bun-types/bun.d.ts#L2036).

You can construct a `BunFile` from multiple sources:

- A string path (`"./data.txt"`)
- A `URL` object
- An `ArrayBuffer` or typed array
- An open file descriptor

## Reading Files with Bun.file

The `BunFile` object provides several async methods for reading content, all returning Promises that can be awaited directly.

### Reading as Text

The `text()` method reads the entire file and resolves to a UTF-8 string:

```typescript
const config = await Bun.file("./config.json").text();
console.log(config);

```

This pattern is validated in the test suite at [`test/js/web/fetch/fetch.test.ts`](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/fetch.test.ts) [[lines 957-967]](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/fetch.test.ts#L957).

### Parsing JSON Directly

Use `json<T>()` to parse the file content as JSON without an intermediate string step:

```typescript
const data = await Bun.file("./data.json").json<Record<string, any>>();
console.log(data);

```

### Streaming Large Files

For memory-efficient processing of large files, use `stream()` which returns a `NodeJS.ReadableStream`:

```typescript
const stream = Bun.file("./large.log").stream();
for await (const chunk of stream) {
  process.stdout.write(chunk);
}

```

Reference implementation in [`test/js/web/fetch/fetch.test.ts`](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/fetch.test.ts) [[lines 1410-1416]](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/fetch.test.ts#L1410).

### Raw Binary Data

Access the file as an `ArrayBuffer` using `arrayBuffer()`:

```typescript
const bytes = await Bun.file("./binary.dat").arrayBuffer();

```

### Partial File Reading

The `slice()` method creates a new `BunFile` representing a subset of the original file without loading it into memory:

```typescript
const partial = Bun.file("./large.txt").slice(0, 1024); // First 1KB
const text = await partial.text();

```

## Writing and Copying Files

While `Bun.file` itself is read-only, Bun provides two primary patterns for writing data: `Bun.write()` for one-shot operations and `writer()` for streaming.

### Copying Files with Bun.write

`Bun.write()` accepts a `BunFile` as the source and copies it to a destination path:

```typescript
// Copy source.txt to dest.txt with specific permissions
await Bun.write("dest.txt", Bun.file("source.txt"), { mode: 0o600 });

```

This mode handling is tested in [`test/regression/issue/25903.test.ts`](https://github.com/oven-sh/bun/blob/main/test/regression/issue/25903.test.ts) [[lines 24-27]](https://github.com/oven-sh/bun/blob/main/test/regression/issue/25903.test.ts#L24).

### Using the Writer API

For incremental writes or piping streams, use `writer()`:

```typescript
const writer = Bun.file("./output.txt").writer();
writer.write("Hello, Bun!\n");
writer.end();              // Finalize the stream
await writer.closed;       // Wait for completion

```

## File Metadata and Management

`BunFile` provides methods for inspecting and modifying the file system entry.

### Checking File Properties

Access the `size` property directly for the byte length, or use `stat()` for detailed metadata:

```typescript
const file = Bun.file("example.txt");
console.log(file.size);  // Synchronous property

const info = await file.stat();
console.log(`Size: ${info.size} bytes, Mode: ${info.mode.toString(8)}`);

```

### Checking Existence and Deleting

Verify a file exists before operations using `exists()`, and remove it with `unlink()` or `delete()`:

```typescript
if (await Bun.file("temp.tmp").exists()) {
  await Bun.file("temp.tmp").unlink();  // or .delete()
}

```

This pattern is demonstrated in [`test/js/web/fetch/blob-write.test.ts`](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/blob-write.test.ts) [[lines 32-34]](https://github.com/oven-sh/bun/blob/main/test/js/web/fetch/blob-write.test.ts#L32).

## Integration with Web APIs

Because `BunFile` inherits from `Blob`, it works natively with the Fetch API. You can return files directly from HTTP handlers:

```typescript
const server = Bun.serve({
  fetch(req) {
    return new Response(Bun.file("./static/index.html"));
  }
});

```

This makes `Bun.file` ideal for both server-side file manipulation and web-compatible data handling.

## Summary

- **`Bun.file`** creates a `Blob`-compatible file handle that accepts paths, URLs, buffers, or file descriptors.
- **Reading methods** include `text()`, `json()`, `arrayBuffer()`, and `stream()` for different use cases.
- **Writing operations** use `Bun.write()` for copying data or `writer()` for streaming writes.
- **Metadata access** via the `size` property and `stat()` method provides file system details.
- **File management** methods like `exists()` and `unlink()` handle lifecycle operations.
- All methods are Promise-based and integrate with the Fetch API and FormData.

## Frequently Asked Questions

### Can Bun.file replace Node.js fs promises?

**`Bun.file` and `Bun.write` provide a modern, Promise-based alternative to Node.js `fs.promises`**, but they serve different purposes. While `Bun.file` offers a `Blob`-compatible interface ideal for web standards integration, Node.js `fs` provides lower-level control over file descriptors and flags. For most high-level read/write operations, `Bun.file` is sufficient and more ergonomic.

### How do I check if a file exists before reading it?

**Use the `exists()` method on the `BunFile` instance.** This returns a Promise that resolves to a boolean indicating whether the file system entry exists:

```typescript
if (await Bun.file("data.json").exists()) {
  const data = await Bun.file("data.json").json();
}

```

### What is the difference between Bun.write and file.writer()?

**`Bun.write()` is a one-shot operation** that copies data from a source (string, buffer, or `BunFile`) to a destination path, suitable for atomic writes. **`file.writer()` returns a writable stream** for incremental writes, appending, or piping data from other streams, which is better for large files or network responses.

### Can I use Bun.file with FormData?

**Yes, `BunFile` can be appended directly to `FormData`** because it inherits from `Blob`. This allows seamless file uploads via the Fetch API:

```typescript
const form = new FormData();
form.append("file", Bun.file("./upload.txt"));
await fetch("https://api.example.com/upload", { method: "POST", body: form });

```