bun-file-io
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseBun File I/O
Bun 文件I/O操作
Bun provides fast, optimized file operations via and .
Bun.file()Bun.write()Bun通过和提供快速、优化的文件操作。
Bun.file()Bun.write()Reading Files
读取文件
Bun.file()
Bun.file()
typescript
// Create file reference (lazy, doesn't read yet)
const file = Bun.file("./data.txt");
// File properties
console.log(file.size); // Size in bytes
console.log(file.type); // MIME type
console.log(file.name); // File path
console.log(await file.exists()); // Boolean
// Read content
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(); // ReadableStreamtypescript
// 创建文件引用(惰性加载,暂不读取)
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(); // 可读流Read Specific Types
读取特定类型文件
typescript
// JSON file
const config = await Bun.file("config.json").json();
// Text file
const content = await Bun.file("readme.md").text();
// Binary file
const binary = await Bun.file("image.png").arrayBuffer();
// With import attributes
import data from "./data.json" with { type: "json" };
import text from "./content.txt" with { type: "text" };typescript
// 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" };Writing Files
写入文件
Bun.write()
Bun.write()
typescript
// Write string
await Bun.write("./output.txt", "Hello World");
// Write JSON
await Bun.write("./data.json", JSON.stringify({ key: "value" }, null, 2));
// Write binary
await Bun.write("./output.bin", new Uint8Array([1, 2, 3]));
// Write from Response
const response = await fetch("https://example.com/image.png");
await Bun.write("./image.png", response);
// Write from another file (efficient copy)
await Bun.write("./copy.txt", Bun.file("./original.txt"));
// Write with options
await Bun.write("./file.txt", "content", {
mode: 0o644, // Unix permissions
});typescript
// 写入字符串
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]));
// 从Response写入
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权限
});Appending
追加内容
typescript
// Using Bun.file writer
const file = Bun.file("./log.txt");
const writer = file.writer();
writer.write("Line 1\n");
writer.write("Line 2\n");
await writer.flush();
writer.end();
// Or use node:fs
import { appendFile } from "node:fs/promises";
await appendFile("./log.txt", "New line\n");typescript
// 使用Bun.file写入器
const file = Bun.file("./log.txt");
const writer = file.writer();
writer.write("Line 1\n");
writer.write("Line 2\n");
await writer.flush();
writer.end();
// 或使用node:fs
import { appendFile } from "node:fs/promises";
await appendFile("./log.txt", "New line\n");Streaming
流操作
Read Stream
读取流
typescript
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;
// Process chunk (Uint8Array)
console.log(value);
}typescript
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);
}Write Stream
写入流
typescript
const file = Bun.file("./output.txt");
const writer = file.writer();
for await (const chunk of dataSource) {
writer.write(chunk);
}
await writer.end();typescript
const file = Bun.file("./output.txt");
const writer = file.writer();
for await (const chunk of dataSource) {
writer.write(chunk);
}
await writer.end();Pipe Streams
管道流
typescript
// File to file
const input = Bun.file("./input.txt");
const output = Bun.file("./output.txt");
await Bun.write(output, input);
// HTTP response to file
const response = await fetch(url);
await Bun.write("./download.zip", response);
// Process stream
const file = Bun.file("./data.txt");
const stream = file.stream();
const transformed = stream.pipeThrough(
new TransformStream({
transform(chunk, controller) {
// Process chunk
controller.enqueue(chunk.toUpperCase());
},
})
);typescript
// 文件到文件
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());
},
})
);Directory Operations
目录操作
typescript
import { readdir, mkdir, rmdir, stat } from "node:fs/promises";
import { existsSync, mkdirSync } from "node:fs";
// List directory
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}`);
}
}
// Create directory
await mkdir("./new-dir", { recursive: true });
// Remove directory
await rmdir("./old-dir", { recursive: true });
// Check if exists
const exists = existsSync("./path");typescript
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(`目录: ${entry.name}`);
} else if (entry.isFile()) {
console.log(`文件: ${entry.name}`);
}
}
// 创建目录
await mkdir("./new-dir", { recursive: true });
// 删除目录
await rmdir("./old-dir", { recursive: true });
// 检查是否存在
const exists = existsSync("./path");Glob Patterns
Glob模式
typescript
// Using Bun.Glob
const glob = new Bun.Glob("**/*.ts");
// Scan directory
for await (const file of glob.scan({ cwd: "./src" })) {
console.log(file); // Relative paths
}
// Get all matches
const files = await Array.fromAsync(glob.scan("./src"));
// With options
const glob2 = new Bun.Glob("**/*.{ts,tsx}");
for await (const file of glob2.scan({
cwd: "./src",
dot: true, // Include dotfiles
absolute: true, // Return absolute paths
onlyFiles: true, // Only files, not directories
})) {
console.log(file);
}
// Test if path matches
const pattern = new Bun.Glob("*.ts");
pattern.match("file.ts"); // true
pattern.match("file.js"); // falsetypescript
// 使用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"); // falseFile Metadata
文件元数据
typescript
import { stat, lstat } from "node:fs/promises";
const stats = await stat("./file.txt");
console.log(stats.size); // Size in bytes
console.log(stats.isFile()); // Is regular file
console.log(stats.isDirectory()); // Is directory
console.log(stats.isSymbolicLink()); // Is symlink
console.log(stats.mtime); // Modified time
console.log(stats.ctime); // Changed time
console.log(stats.atime); // Access time
console.log(stats.mode); // Permissionstypescript
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); // 权限Path Operations
路径操作
typescript
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"); // Absolute path
// Bun-specific
import.meta.dir; // Directory of current file
import.meta.file; // Filename
import.meta.path; // Full pathtypescript
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专属API
import.meta.dir; // 当前文件所在目录
import.meta.file; // 当前文件名
import.meta.path; // 当前文件完整路径Common Patterns
常见使用模式
Read JSON Config
读取JSON配置
typescript
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");typescript
async function loadConfig<T>(path: string): Promise<T> {
const file = Bun.file(path);
if (!(await file.exists())) {
throw new Error(`配置文件未找到: ${path}`);
}
return file.json();
}
const config = await loadConfig<AppConfig>("./config.json");Copy Directory
复制目录
typescript
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));
}
}
}typescript
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));
}
}
}Watch Files
监听文件
typescript
import { watch } from "node:fs";
watch("./src", { recursive: true }, (event, filename) => {
console.log(`${event}: ${filename}`);
});
// Or with Bun's built-in (faster)
const watcher = Bun.spawn(["bun", "--watch", "src/index.ts"]);typescript
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"]);Temp Files
临时文件
typescript
import { mkdtemp } from "node:fs/promises";
import { tmpdir } from "node:os";
import { join } from "node:path";
// Create temp directory
const tempDir = await mkdtemp(join(tmpdir(), "app-"));
console.log(tempDir); // /tmp/app-xxxxx
// Write temp file
const tempFile = join(tempDir, "data.txt");
await Bun.write(tempFile, "temporary data");typescript
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, "临时数据");Common Errors
常见错误
| Error | Cause | Fix |
|---|---|---|
| File not found | Check path, use exists() |
| Permission denied | Check file permissions |
| Is a directory | Use readdir() for directories |
| Already exists | Use recursive: true for mkdir |
| 错误 | 原因 | 解决方法 |
|---|---|---|
| 文件未找到 | 检查路径,使用exists()方法 |
| 权限不足 | 检查文件权限 |
| 目标是目录 | 对目录使用readdir()方法 |
| 文件已存在 | 创建目录时使用recursive: true选项 |
When to Load References
何时加载参考文档
Load when:
references/streams-advanced.md- Transform streams
- Compression streams
- Binary protocols
Load when:
references/performance.md- Large file handling
- Memory optimization
- Concurrent operations
当涉及以下内容时,加载:
references/streams-advanced.md- 转换流
- 压缩流
- 二进制协议
当涉及以下内容时,加载:
references/performance.md- 大文件处理
- 内存优化
- 并发操作