首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Java BufferedInputStream 緩衝機制解析:read() 雖同基類但內部緩衝區提升讀取效能

     編輯:程式設計綜合問答

核心誤區澄清

BufferedInputStream.read() **方法簽名與 `InputStream.read()` 相同**,但**內部實現完全不同**。「緩衝」不在方法簽名體現,而在於**內部維護一個 byte[] 緩衝區 (默認 8192 字節)**。

源碼級對比 (JDK 17)

InputStream.read() — 抽象方法,無默認實現


public abstract int read() throws IOException;

子類 (如 `FileInputStream`) 每次調用**直接發起系統調用** 讀取 1 字節,極慢。

BufferedInputStream.read() — 核心緩衝邏輯


private byte[] buf;           // 緩衝區
private int count;            // 緩衝區有效字節數
private int pos;              // 當前讀取位置

public synchronized int read() throws IOException {
    if (pos >= count) {       // 緩衝區耗盡
        fill();               // 批量填充緩衝區
        if (pos >= count) return -1;
    }
    return buf[pos++] & 0xFF; // 從緩衝區直接取字節 (極快,用戶態)
}

private void fill() throws IOException {
    // 一次系統調用讀取大量數據到 buf
    int n = getInIfOpen().read(buf, 0, buf.length);
    if (n > 0) {
        count = n;
        pos = 0;
    }
}

緩衝效能量化

BufferedReader vs BufferedInputStream 區別

場景系統調用次數 (讀 1MB)用戶態/內核態切換相對耗時
FileInputStream.read()1,048,576 次 (每字節 1 次)極多基準 100%
BufferedInputStream.read() (8KB 緩衝)128 次 (1MB/8KB)極少**< 1%**
BufferedInputStream.read(byte[], off, len)1 次 (直接複製緩衝區)最少最快

為什麼 BufferedInputStream 沒有 readLine()?

**字節流無「行」概念**。行分隔符 (\n, \r\n) 是文本協議約定,需先解碼為字符流才能識別。`BufferedReader` 內部持有 `InputStreamReader` 完成解碼,再按行緩衝。

正確使用姿勢


// 文本文件:BufferedReader (按行、自動解碼)
try (BufferedReader br = new BufferedReader(
        new InputStreamReader(new FileInputStream("log.txt"), StandardCharsets.UTF_8))) {
    String line;
    while ((line = br.readLine()) != null) { process(line); }
}

// 二進制文件/網絡流:BufferedInputStream (大塊讀取)
try (BufferedInputStream bis = new BufferedInputStream(
        new FileInputStream("image.jpg"), 65536)) {  // 64KB 緩衝區
    byte[] buffer = new byte[4096];
    int len;
    while ((len = bis.read(buffer)) != -1) {
        outputStream.write(buffer, 0, len);
    }
}

// 裝飾器模式鏈:FileInputStream → BufferedInputStream → DataInputStream / ObjectInputStream

總結

BufferedInputStream.read() **雖與基類簽名相同,但內部實現「批量系統調用填充緩衝區 + 用戶態緩衝區取數」**,將系統調用次數降低 3-4 個數量級。**緩衝本質是「用空間換時間,用批量換頻次」**。字符流用 `BufferedReader.readLine()`,字節流用 `BufferedInputStream.read(byte[])` 最大化吞吐。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
特性BufferedReader (字符流)BufferedInputStream (字節流)
讀取單位字符字節
核心方法readLine() (按行讀取)read() / read(byte[])
解碼職責內部包裝 `InputStreamReader` (字節→字符)無解碼,原始字節
適用場景文本文件、配置文件、日志分析二進制文件 (圖片、視頻、壓縮包)、網絡流