NIOBuffer缓冲区读写操作

wen java案例 1

NIO Buffer 缓冲区读写操作详解

基本概念

Buffer是NIO中存储数据的容器,本质是一个内存块,用于Channel之间的数据读写,核心属性:

NIOBuffer缓冲区读写操作

属性 说明
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

性能优化建议

  1. 合理分配大小:避免过小导致频繁扩容,避免过大浪费内存
  2. 重用缓冲区:使用clear()compact()而不是重新分配
  3. 批量操作:优先使用批量put/get数组操作
  4. 直接缓冲区:I/O密集型场景考虑DirectBuffer
  5. 避免碎片:使用compact()而不是clear()保留未读数据

常见错误

错误 原因 解决
BufferUnderflowException 读取超出position 检查remaining()
BufferOverflowException 写入超出limit 检查剩余空间
IllegalArgumentException 创建负容量 检查分配参数
ReadOnlyBufferException 修改只读缓冲区 检查isReadOnly()

读写操作核心流程

写入数据 → flip() → 读取数据 → clear()/compact() → 循环

关键原则

  • 写模式:position指向写入位置,limit=capacity
  • 读模式:position指向读取位置,limit=数据末尾
  • 切换模式:必须调用flip()clear()

通过深入理解这些概念,您可以高效地使用NIO Buffer进行各种I/O操作。

抱歉,评论功能暂时关闭!