Bun文件输入输出操作技能 BunFileI/O

这个技能专注于使用Bun运行时进行高效的文件输入输出操作,包括文件读取、写入、流处理、目录管理、全局模式匹配和元数据访问。适用于后端开发、数据处理和文件系统优化场景,关键词:Bun, 文件I/O, 流处理, 目录操作, JavaScript, 后端开发, 文件系统, SEO优化。

后端开发 0 次安装 0 次浏览 更新于 3/8/2026

name: Bun文件I/O description: 用于Bun文件I/O:Bun.file、Bun.write、流、目录、全局模式、元数据。 version: 1.0.0

Bun文件I/O

Bun通过Bun.file()Bun.write()提供快速、优化的文件操作。

读取文件

Bun.file()

// 创建文件引用(惰性,尚未读取)
const file = Bun.file("./data.txt");

// 文件属性
console.log(file.size);        // 字节大小
console.log(file.type);        // MIME类型
console.log(file.name);        // 文件路径
console.log(await file.exists()); // 布尔值

// 读取内容
const text = await file.text();
const json = await file.json();
const buffer = await file.arrayBuffer();
const bytes = await file.bytes();   // Uint8Array
const stream = file.stream();       // ReadableStream

读取特定类型

// JSON文件
const config = await Bun.file("config.json").json();

// 文本文件
const content = await Bun.file("readme.md").text();

// 二进制文件
const binary = await Bun.file("image.png").arrayBuffer();

// 使用导入属性
import data from "./data.json" with { type: "json" };
import text from "./content.txt" with { type: "text" };

写入文件

Bun.write()

// 写入字符串
await Bun.write("./output.txt", "Hello World");

// 写入JSON
await Bun.write("./data.json", JSON.stringify({ key: "value" }, null, 2));

// 写入二进制
await Bun.write("./output.bin", new Uint8Array([1, 2, 3]));

// 从响应写入
const response = await fetch("https://example.com/image.png");
await Bun.write("./image.png", response);

// 从另一个文件写入(高效复制)
await Bun.write("./copy.txt", Bun.file("./original.txt"));

// 带选项写入
await Bun.write("./file.txt", "content", {
  mode: 0o644,  // Unix权限
});

追加

// 使用Bun.file写入器
const file = Bun.file("./log.txt");
const writer = file.writer();

writer.write("Line 1
");
writer.write("Line 2
");
await writer.flush();
writer.end();

// 或使用node:fs
import { appendFile } from "node:fs/promises";
await appendFile("./log.txt", "New line
");

流操作

读取流

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

const reader = stream.getReader();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  // 处理块(Uint8Array)
  console.log(value);
}

写入流

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

for await (const chunk of dataSource) {
  writer.write(chunk);
}

await writer.end();

管道流

// 文件到文件
const input = Bun.file("./input.txt");
const output = Bun.file("./output.txt");
await Bun.write(output, input);

// HTTP响应到文件
const response = await fetch(url);
await Bun.write("./download.zip", response);

// 处理流
const file = Bun.file("./data.txt");
const stream = file.stream();

const transformed = stream.pipeThrough(
  new TransformStream({
    transform(chunk, controller) {
      // 处理块
      controller.enqueue(chunk.toUpperCase());
    },
  })
);

目录操作

import { readdir, mkdir, rmdir, stat } from "node:fs/promises";
import { existsSync, mkdirSync } from "node:fs";

// 列出目录
const files = await readdir("./src");
const filesWithTypes = await readdir("./src", { withFileTypes: true });

for (const entry of filesWithTypes) {
  if (entry.isDirectory()) {
    console.log(`Dir: ${entry.name}`);
  } else if (entry.isFile()) {
    console.log(`File: ${entry.name}`);
  }
}

// 创建目录
await mkdir("./new-dir", { recursive: true });

// 移除目录
await rmdir("./old-dir", { recursive: true });

// 检查是否存在
const exists = existsSync("./path");

全局模式

// 使用Bun.Glob
const glob = new Bun.Glob("**/*.ts");

// 扫描目录
for await (const file of glob.scan({ cwd: "./src" })) {
  console.log(file); // 相对路径
}

// 获取所有匹配
const files = await Array.fromAsync(glob.scan("./src"));

// 带选项
const glob2 = new Bun.Glob("**/*.{ts,tsx}");
for await (const file of glob2.scan({
  cwd: "./src",
  dot: true,           // 包含隐藏文件
  absolute: true,      // 返回绝对路径
  onlyFiles: true,     // 仅文件,不包括目录
})) {
  console.log(file);
}

// 测试路径是否匹配
const pattern = new Bun.Glob("*.ts");
pattern.match("file.ts");    // true
pattern.match("file.js");    // false

文件元数据

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

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

console.log(stats.size);          // 字节大小
console.log(stats.isFile());      // 是否为常规文件
console.log(stats.isDirectory()); // 是否为目录
console.log(stats.isSymbolicLink()); // 是否为符号链接
console.log(stats.mtime);         // 修改时间
console.log(stats.ctime);         // 变化时间
console.log(stats.atime);         // 访问时间
console.log(stats.mode);          // 权限

路径操作

import { join, dirname, basename, extname, resolve } from "node:path";

const filePath = "/home/user/project/src/index.ts";

join("a", "b", "c");           // "a/b/c"
dirname(filePath);             // "/home/user/project/src"
basename(filePath);            // "index.ts"
basename(filePath, ".ts");     // "index"
extname(filePath);             // ".ts"
resolve("./relative");         // 绝对路径

// Bun特定
import.meta.dir;   // 当前文件所在目录
import.meta.file;  // 文件名
import.meta.path;  // 完整路径

常见模式

读取JSON配置

async function loadConfig<T>(path: string): Promise<T> {
  const file = Bun.file(path);
  if (!(await file.exists())) {
    throw new Error(`Config not found: ${path}`);
  }
  return file.json();
}

const config = await loadConfig<AppConfig>("./config.json");

复制目录

import { readdir, mkdir, stat } from "node:fs/promises";
import { join } from "node:path";

async function copyDir(src: string, dest: string) {
  await mkdir(dest, { recursive: true });

  for (const entry of await readdir(src, { withFileTypes: true })) {
    const srcPath = join(src, entry.name);
    const destPath = join(dest, entry.name);

    if (entry.isDirectory()) {
      await copyDir(srcPath, destPath);
    } else {
      await Bun.write(destPath, Bun.file(srcPath));
    }
  }
}

监视文件

import { watch } from "node:fs";

watch("./src", { recursive: true }, (event, filename) => {
  console.log(`${event}: ${filename}`);
});

// 或使用Bun内置(更快)
const watcher = Bun.spawn(["bun", "--watch", "src/index.ts"]);

临时文件

import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";

// 创建临时目录
const tempDir = await mkdtemp(join(tmpdir(), "app-"));
console.log(tempDir); // /tmp/app-xxxxx

// 写入临时文件
const tempFile = join(tempDir, "data.txt");
await Bun.write(tempFile, "temporary data");

常见错误

错误 原因 解决方案
ENOENT 文件未找到 检查路径,使用exists()
EACCES 权限被拒绝 检查文件权限
EISDIR 是目录 对目录使用readdir()
EEXIST 已存在 对mkdir使用recursive: true

何时加载参考

加载references/streams-advanced.md当:

  • 转换流
  • 压缩流
  • 二进制协议

加载references/performance.md当:

  • 大文件处理
  • 内存优化
  • 并发操作