Netty 学习笔记(一) —— NIO 的 ByteBuffer

Channel 中的数据都需要暂存到 Buffer 中,才可以被程序使用。
因为 Channel 没有方向性,所以 Buffer 引入了读模式和写模式来区分读写

Buffer 的作用是 存一批数据再处理,提高 IO 的效率 。没有 Buffer 就只能一个字节一个字节的处理

public static void main(String[] args) throws IOException {
    // 1.读取文件
    FileChannel channel = new FileInputStream("/Users/wangzhihao/workspace/study-demo/netty-demo/data.txt").getChannel();

    // 2.获取 buffer
    ByteBuffer buffer = ByteBuffer.allocate(10);

    while (true) {
        // 3.将文件内容读取到 buffer
        int read = channel.read(buffer);
        if (read == -1) {
            break;
        }

        // 4.将 buffer 切换到读模式
        buffer.flip();

        // 5.读取 buffer 中的内容
        while (buffer.hasRemaining()) {
            byte b = buffer.get();
            System.out.println("(char)b = " + (char)b);
        }

        // 6.将 buffer 切换回写模式
        buffer.clear();
    }
}
在 UTF-8 编码中,一个
	常见字母数字占一个字节
	拉丁文占两个字节
	中韩日文占三个字节
	其他罕见字符占四个字节
在 GBK 编码中,一个
	中文字符占 2 个字节

image.png

ByteBuffer

主要实现类

HeapByteBuffer

JVM 内的堆内存,读写操作效率低,会受到 GC 影响

DirectByteBuffer

OS 内存,读写操作效率高,不会受到 GC 影响。但 不主动析构,会造成内存的泄漏

image.png

获取方式

  1. ByteBuffer.allocate() 一旦分配空间,大小不可以动态调整
  2. encode() 字符串的 encode() 方法

核心结构

ByteBuffer是一个类似数组的结构,整个结构中包含三个主要的状态

  1. Capacity
    buffer的容量,类似于数组的size
  2. Position
    buffer当前缓存的下标,在读取操作时记录读到了那个位置,在写操作时记录写到了那个位置。从0开始,每读取一次,下标+1
  3. Limit
    读写限制,在读操作时,设置了你能读多少字节的数据,在写操作时,设置了你还能写多少字节的数据

所谓的读写模式,本质上就是这几个状态的变化。主要有Position和Limit联合决定了Buffer的读写数据区域。

核心 API

写数据
  1. channel.read(buffer)
  2. buffer.put(byte)
  3. buffer.put(byte[])
读数据
  1. channel 的 write 方法,从 buffer 中读取数据并写入文件(buffer)

  2. buffer.get() 方法,每调用一次都会改变 position 的位置

  3. rewind 方法,将 position 重置为 0 ,用于重复读取数据

        // 获取 buffer
        ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put(new byte[]{'a', 'b', 'c'});
        // 将 buffer 切换到读模式
        buffer.flip();
    
        // 读取 buffer 中的内容
        while (buffer.hasRemaining()) {
            byte b = buffer.get();
            System.out.println("(char)b = " + (char) b);
        }
    
        System.out.println("------------------------");
        // 将 position 置为 0
        buffer.rewind();
        // 读取 buffer 中的内容
        while (buffer.hasRemaining()) {
            byte b = buffer.get();
            System.out.println("(char)b = " + (char) b);
        }
    
  4. mark & reset 方法, 通过 mark 方法标记当前 position ,通过 reset 方法跳回标记,重新从 mark 位置执行(获取数据)

  5. get(i) 方法,获取特定 position 上的数据,不会影响 position

tip
StandardCharsets.UTF_8.encode("pine"); 

encode 和 wrap 方法转字符串为 buffer 会自动设置读模式,再次手动设置会读不到数据(看 flip() 源码)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值