BufferedWriter 是字元導向的緩衝輸出流,繼承自 Writer。它的核心使命是為其他字元輸出流(如 FileWriter、OutputStreamWriter)提供緩衝功能,減少底層 I/O 系統呼叫次數,大幅提升寫入效能。預設緩衝區大小 8192 字元(16 KB),亦可自訂。
// 建構子
BufferedWriter(Writer out) // 預設 8KB 緩衝
BufferedWriter(Writer out, int sz) // 自訂緩衝區大小
// 核心寫入
void write(int c) // 單字元
void write(char[] cbuf, int off, int len) // 字元陣列片段
void write(String s, int off, int len) // 字串片段
// 特有功能
void newLine() // 寫入系統行分隔符(line.separator)
void flush() // 強制刷新緩衝區至底層流
void close() // 關閉前自動 flush
public class BufferedWriter extends Writer {
private Writer out; // 底層輸出流
private char[] cb; // 字元緩衝陣列
private int nChars; // 緩衝區總容量
private int nextChar = 0; // 下一個寫入位置
private String lineSeparator; // 系統行分隔符
// 預設 8192 字元
private static int defaultCharBufferSize = 8192;
public BufferedWriter(Writer out, int sz) {
super(out);
if (sz <= 0) throw new IllegalArgumentException("Buffer size <= 0");
this.out = out;
cb = new char[sz];
nChars = sz;
lineSeparator = AccessController.doPrivileged(
new GetPropertyAction("line.separator"));
}
}
// 單字元寫入:緩衝區滿則自動 flush
public void write(int c) throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar >= nChars) flushBuffer();
cb[nextChar++] = (char) c;
}
}
// 陣列寫入:大資料直接寫入底層,小資料進緩衝
public void write(char[] cbuf, int off, int len) throws IOException {
synchronized (lock) {
ensureOpen();
if (len >= nChars) { // 超過緩衝區大小,直接寫入底層
flushBuffer();
out.write(cbuf, off, len);
return;
}
if (len > nChars - nextChar) // 剩餘空間不足,先 flush
flushBuffer();
System.arraycopy(cbuf, off, cb, nextChar, len);
nextChar += len;
}
}
// 刷新緩衝區至底層流
void flushBuffer() throws IOException {
synchronized (lock) {
ensureOpen();
if (nextChar == 0) return;
out.write(cb, 0, nextChar);
nextChar = 0;
}
}
newLine() 寫入 lineSeparator(Windows 為 \r\n,Linux/macOS 為 \n),並視 autoFlush 決定是否立即刷新。這比硬編碼 \n 更具可移植性。
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
public class BufferedWriterDemo {
public static void main(String[] args) {
Path path = Path.of("buffered_demo.txt");
// 現代寫法:Files.newBufferedWriter 自動處理編碼與資源
try (BufferedWriter bw = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) {
bw.write("第一行:BufferedWriter 效能測試");
bw.newLine();
bw.write("第二行:支援中文與 Unicode");
bw.newLine();
// 批次寫入字元陣列
char[] data = "第三行:字元陣列批次寫入".toCharArray();
bw.write(data, 0, data.length);
bw.newLine();
// 寫入字串片段
String msg = "第四行:部分字串寫入示範";
bw.write(msg, 5, msg.length() - 5); // 略過 "第四行:"
bw.newLine();
bw.flush(); // 手動刷新,確保資料落盤
} catch (IOException e) {
e.printStackTrace();
}
// 驗證內容
try {
System.out.println(Files.readString(path));
} catch (IOException e) {
e.printStackTrace();
}
}
}
| 場景 | 建議緩衝區大小 | 說明 |
|---|---|---|
| 一般文字檔寫入 | 8 KB (預設) | 平衡記憶體與系統呼叫頻率 |
| 大量行輸出(日誌、報表) | 16-64 KB | 減少 flush 頻率,提升吞吐量 |
| 小檔案、低延遲需求 | 1-4 KB | 降低記憶體佔用,資料更快可見 |
| 已知平均行長 | 行長倍數 | 避免緩衝區殘留空間浪費 |
newLine(),避免 Windows 下行分隔符錯誤。new BufferedWriter(new BufferedWriter(...)) 無意義且增加複雜度。FileWriter 使用平台預設編碼,建議改用 OutputStreamWriter 或 Files.newBufferedWriter 指定 UTF-8。// 組合模式:緩衝 + 格式化 + 自動刷新
try (PrintWriter pw = new PrintWriter(
new BufferedWriter(new FileWriter("formatted.log")), true)) {
pw.printf("[%s] INFO: 處理完成,耗時 %d ms%n",
java.time.LocalTime.now(), 123);
}
BufferedWriter 是 Java 高效文字寫入的基石,理解其緩衝策略、刷新時機與跨平台行分隔符處理,能讓你的檔案輸出既快速又可靠。