BufferedReader.readLine() 無論讀一行還是多字符,底層最終都調用 read() 逐字符從磁盤讀取,在內存中拼裝成行。核心邏輯:
read() 獲取單字符 int ch。'\r' 忽略;遇到 '\n' 返回已拼裝字符串。-1)且緩衝區有內容 → 返回內容;否則返回 null。public class MyBufferedReader {
private final Reader in;
public MyBufferedReader(Reader in) { this.in = in; }
public String myReadLine() throws IOException {
StringBuilder sb = new StringBuilder();
int ch;
while ((ch = in.read()) != -1) {
if (ch == '\r') continue; // 忽略 CR
if (ch == '\n') return sb.toString(); // 遇到 LF 返回行
sb.append((char) ch);
}
return sb.length() > 0 ? sb.toString() : null; // 文件末尾無換行符
}
public void myClose() throws IOException { in.close(); }
}
// 測試
public static void main(String[] args) throws IOException {
try (MyBufferedReader br = new MyBufferedReader(new FileReader("buf.txt"))) {
String line;
while ((line = br.myReadLine()) != null) System.out.println(line);
}
}
當想增強現有對象功能時,定義裝飾類持有被裝飾對象引用,委託核心邏輯並在前後添加增強行為。
// 節點流(被裝飾者)
FileInputStream fis = new FileInputStream("a.txt");
// 處理流(裝飾者)層層包裹
BufferedInputStream bis = new BufferedInputStream(fis); // 增加緩衝
DataInputStream dis = new DataInputStream(bis); // 增加基本類型讀取
// 使用
int i = dis.readInt();
public class CountingInputStream extends InputStream {
private final InputStream in;
private long count = 0;
public CountingInputStream(InputStream in) { this.in = in; }
@Override public int read() throws IOException {
int b = in.read();
if (b != -1) count++;
return b;
}
@Override public int read(byte[] b, int off, int len) throws IOException {
int n = in.read(b, off, len);
if (n > 0) count += n;
return n;
}
public long getCount() { return count; }
}
// 使用
try (CountingInputStream cis = new CountingInputStream(new FileInputStream("big.dat"))) {
cis.readAllBytes();
System.out.println("總讀取字節: " + cis.getCount());
}
readLine() 本質是循環 read() + 緩衝拼裝,理解此原理可自定義行讀取邏輯(如自定義分隔符)。BufferedReader/BufferedInputStream 等標準裝飾器,僅在有特殊統計、過濾、轉換需求時自定義裝飾類。