首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java NIO 文件讀寫提速(二):Buffer 內部機制深度解析與 clear/flip 圖解

     編輯:Java 相關知識

系列第二篇,深入剖析 Buffer 核心狀態變量(position、limit、capacity、mark)與關鍵操作 clear()、flip()、rewind()、compact() 的內部邏輯,透過狀態機圖解讓你徹底掌握「讀寫切換」本質。

Buffer 核心四大屬性


public abstract class Buffer {
    // 0 <= mark <= position <= limit <= capacity
    private int mark = -1;      // 標記位置,reset() 回退用
    private int position = 0;   // 下一次讀/寫位置
    private int limit;          // 邊界:還能讀/寫多少
    private int capacity;       // 固定容量
}

狀態機圖解:寫模式 → 讀模式 → 寫模式

初始狀態(分配後)

capacity=8, limit=8, position=0, mark=-1
[ ][ ][ ][ ][ ][ ][ ][ ]
 ^                       ^
 pos=0                  limit=8

寫入 3 個元素後

position=3, limit=8
[ A ][ B ][ C ][ ][ ][ ][ ][ ]
 ^                       ^
 pos=3                  limit=8

執行 flip():切換到讀模式


public final Buffer flip() {
    limit = position; // 讀取邊界 = 已寫入數量
    position = 0;     // 從頭讀
    mark = -1;
    return this;
}
limit=3, position=0
[ A ][ B ][ C ][ ][ ][ ][ ][ ]
 ^                  ^
 pos=0             limit=3

讀取 2 個元素後

position=2, limit=3
[ A ][ B ][ C ][ ][ ][ ][ ][ ]
       ^           ^
       pos=2      limit=3

執行 clear():切換到寫模式(清空狀態,數據不清零)


public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}
position=0, limit=8 (capacity)
[ A ][ B ][ C ][ ][ ][ ][ ][ ]
 ^                       ^
 pos=0                  limit=8
clear() 不清零數據,僅重置位置標記,舊數據會被後續寫入覆蓋。

四大核心操作對照表

操作適用場景positionlimitmark語義
flip()寫完 → 讀取=0=position=-1鎖定已寫數據範圍,準備讀取
clear()讀完 → 重寫=0=capacity=-1準備覆寫整個緩衝區
rewind()重新讀取=0不變=-1position 歸零,limit 不變(重讀已讀數據)
compact()未讀完 → 續寫=剩餘數據量=capacity=-1未讀數據移至頭部,position 接在後面續寫

compact() 圖解:未讀完續寫

讀取 2 個後:position=2, limit=3
[ A ][ B ][ C ][ ][ ][ ][ ][ ]
       ^           ^
compact() 後:
[ C ][ ][ ][ ][ ][ ][ ][ ]
 ^                  ^
pos=1             limit=8
// C 移至頭部,position=1 可續寫

mark()/reset():標記與回退


buffer.mark();    // mark = position
// ... 讀取若干 ...
buffer.reset();   // position = mark (回退到標記處)
僅支援單一標記,巢狀調用會覆蓋。

實戰:通道間高效傳輸循環


ByteBuffer buf = ByteBuffer.allocateDirect(1024 * 64); // 直接緩衝區,零拷貝
while (inChannel.read(buf) != -1) {
    buf.flip();           // 切換讀模式
    outChannel.write(buf); // 寫出(write 會更新 position)
    buf.compact();        // 未寫完數據移頭部,續讀
}
buf.flip();
while (buf.hasRemaining()) outChannel.write(buf); // 刷新殘留

直接緩衝區 vs 堆緩衝區

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
類型分配優點缺點
Heap Bufferallocate()GC 管理、安全通道傳輸需中間拷貝
Direct BufferallocateDirect()零拷貝、OS 原生 I/O分配/釋放貴、不受堆限制、需手動管理或靠 GC 清理