NIO Buffer 缓冲区读写操作详解
基本概念
Buffer是NIO中存储数据的容器,本质是一个内存块,用于Channel之间的数据读写,核心属性:

| 属性 | 说明 |
|---|---|
| capacity | 缓冲区容量(固定不变) |
| position | 当前读写位置(从0开始) |
| limit | 可读/写的最大位置 |
| mark | 标记位置(可选) |
关系:0 <= mark <= position <= limit <= capacity |
核心读写模式
写模式(写入Buffer)
// 1. 创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(10);
// 2. 写入数据
buffer.put((byte) 65); // position=1
buffer.put("Hello".getBytes()); // position=6
// 3. 切换到读模式
buffer.flip(); // limit=position, position=0
读模式(从Buffer读取)
// 4. 读取数据 byte b = buffer.get(); // position=1 ByteBuffer slice = buffer.slice(); // 读取剩余数据 // 5. 重复读取(重置position) buffer.rewind(); // position=0, limit不变 // 6. 清空缓冲区 buffer.clear(); // position=0, limit=capacity
关键方法详解
写入方法
// 绝对写入(指定位置) buffer.put(0, (byte) 65); // 相对写入(当前位置) buffer.put((byte) 66); // position+1 buffer.putInt(123); // 写入int(4字节) buffer.putLong(456L); // 写入long(8字节) // 批量写入 byte[] data = "World".getBytes(); buffer.put(data, 0, data.length);
读取方法
// 绝对读取 byte b = buffer.get(0); // 不改变position // 相对读取 byte b = buffer.get(); // position+1 int i = buffer.getInt(); // 读取int long l = buffer.getLong(); // 读取long // 批量读取 byte[] dst = new byte[5]; buffer.get(dst, 0, 5); // 读取5字节到数组
状态切换方法
| 方法 | 功能 | 修改的属性 |
|---|---|---|
flip() |
写→读 | limit=position, position=0 |
clear() |
任意→写 | position=0, limit=capacity |
rewind() |
重复读 | position=0, limit不变 |
compact() |
压缩未读数据 | 保留未读数据,准备写入 |
完整示例
public class BufferDemo {
public static void main(String[] args) {
// 1. 分配缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
// 2. 写入数据(写模式)
String data = "Hello NIO Buffer";
buffer.put(data.getBytes());
System.out.println("写入后: position=" + buffer.position()
+ ", limit=" + buffer.limit());
// 3. 切换到读模式
buffer.flip();
System.out.println("flip后: position=" + buffer.position()
+ ", limit=" + buffer.limit());
// 4. 读取数据
byte[] bytes = new byte[buffer.limit()];
buffer.get(bytes);
System.out.println("读取内容: " + new String(bytes));
// 5. 复读(rewind)
buffer.rewind();
byte[] reRead = new byte[5];
buffer.get(reRead);
System.out.println("重新读取前5字节: " + new String(reRead));
// 6. 清空并重新写入
buffer.clear();
System.out.println("clear后: position=" + buffer.position()
+ ", limit=" + buffer.limit());
// 7. 使用compact保留未读数据
buffer.put("New data".getBytes());
buffer.flip();
buffer.get(); // 读取1字节
buffer.compact(); // 保留未读数据
buffer.put(" appended".getBytes());
buffer.flip();
byte[] result = new byte[buffer.limit()];
buffer.get(result);
System.out.println("compact后内容: " + new String(result));
}
}
高级用法
只读缓冲区
ByteBuffer readOnly = buffer.asReadOnlyBuffer(); // readOnly.put(...) // 会抛出ReadOnlyBufferException
直接缓冲区(Direct Buffer)
ByteBuffer directBuffer = ByteBuffer.allocateDirect(1024); // 零拷贝,适合网络传输,但创建/销毁开销大
缓冲区分片
buffer.position(2); buffer.limit(6); ByteBuffer slice = buffer.slice(); // 共享底层数据 slice.put(0, (byte) 88); // 会影响原buffer
性能优化建议
- 合理分配大小:避免过小导致频繁扩容,避免过大浪费内存
- 重用缓冲区:使用
clear()或compact()而不是重新分配 - 批量操作:优先使用批量put/get数组操作
- 直接缓冲区:I/O密集型场景考虑DirectBuffer
- 避免碎片:使用
compact()而不是clear()保留未读数据
常见错误
| 错误 | 原因 | 解决 |
|---|---|---|
| BufferUnderflowException | 读取超出position | 检查remaining() |
| BufferOverflowException | 写入超出limit | 检查剩余空间 |
| IllegalArgumentException | 创建负容量 | 检查分配参数 |
| ReadOnlyBufferException | 修改只读缓冲区 | 检查isReadOnly() |
读写操作核心流程:
写入数据 → flip() → 读取数据 → clear()/compact() → 循环
关键原则:
- 写模式:position指向写入位置,limit=capacity
- 读模式:position指向读取位置,limit=数据末尾
- 切换模式:必须调用
flip()或clear()
通过深入理解这些概念,您可以高效地使用NIO Buffer进行各种I/O操作。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播