3.NIO-ByteBuffer常用方法,分散读集中写,黏包半包

1.2.3、ByteBuffer常见方法
public class TestBufferRead {
    public static void main(String[] args) {
        ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put(new byte[]{'a', 'b', 'c', 'd'});
        buffer.flip();

        buffer.get(new byte[4]);//读四个字节
        ByteBufferUtil.debugAll(buffer);
        buffer.rewind();//从头开始读
        System.out.println((char) buffer.get());
        ByteBufferUtil.debugAll(buffer);

        buffer.mark();//记录position位置
        System.out.println((char) buffer.get());
        buffer.reset();//将position复位到mark位置
        System.out.println((char) buffer.get());
        ByteBufferUtil.debugAll(buffer);

        System.out.println((char) buffer.get(3));//根据下标读取,position不变
        ByteBufferUtil.debugAll(buffer);
    }
}

分配空间

//返回的是HeapByteBuffer类型ByteBuffer 分配的堆内存
allocate();
//返回的是HDirectByteBuffer类型ByteBuffer 分配的是只直接的物理内存,读写快,分配慢
ByteBuffer.allocateDirect(16);

从buffer读取

//从buffer读,写入channel
channel.write(buffer);
//直接读,返回byte
buffer.get();

get方法会让position向后移,如果想要重复读取数据

  • rewind() 方法会将position=0
  • get(int i) 通过索引获取内容,position不会移动

mark reset

  • mark 是在读取时,做一个标记
  • reset 即使 position 改变,只要调用 reset 就能回到 mark 的位置

get(int index)

  • 读取指定下标数据

字符串与Buffer互转

public class TestByteBufferString {
    public static void main(String[] args) {
        //1.字符串转byteBuffer
        ByteBuffer buffer = ByteBuffer.allocate(10);
        buffer.put("hello".getBytes());
        ByteBufferUtil.debugAll(buffer);

        //2.Charset 切换到读模式
        ByteBuffer buffer2 = StandardCharsets.UTF_8.encode("hello");
        ByteBufferUtil.debugAll(buffer2);

        //3.wrap 切换到读模式
        ByteBuffer buffer3 = ByteBuffer.wrap("hello".getBytes());
        ByteBufferUtil.debugAll(buffer3);

        //decode只能转读模式
        CharBuffer charBuffer = StandardCharsets.UTF_8.decode(buffer2);
        System.out.println(charBuffer.toString());

    }
}
1.2.4、分散读
//分散读取,可以将数据填充至多个 buffer
public class TestScatteringReads {
    public static void main(String[] args) {
        try {
            FileChannel channel = new RandomAccessFile("data.txt", "r").getChannel();
            ByteBuffer buffer1 = ByteBuffer.allocate(4);
            ByteBuffer buffer2 = ByteBuffer.allocate(5);
            ByteBuffer buffer3 = ByteBuffer.allocate(5);
            channel.read(new ByteBuffer[]{buffer1, buffer2, buffer3});
            buffer1.flip();
            buffer2.flip();
            buffer3.flip();

            ByteBufferUtil.debugAll(buffer1);
            System.out.println(buffer1.get());


        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
1.2.5、集中写
//集中写,可以将多个 buffer 的数据填充至 channel
public class TestGatherWrites {
    public static void main(String[] args) {

        ByteBuffer buffer1 = StandardCharsets.UTF_8.encode("hello");
        ByteBuffer buffer2 = StandardCharsets.UTF_8.encode("world");
        ByteBuffer buffer3 = StandardCharsets.UTF_8.encode("你好");
        try {
            RandomAccessFile file = new RandomAccessFile("a.txt", "rw");
            FileChannel channel = file.getChannel();
            channel.write(new ByteBuffer[]{buffer1, buffer2, buffer3});
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
1.2.6、黏包,半包

网络上有多条数据发送给服务端,数据之间使用 \n 进行分隔
但由于某种原因这些数据在接收时,被进行了重新组合,例如原始数据有3条为

  • Hello,world\n
  • I'm zhangsan\n
  • How are you?\n

变成了下面的两个 byteBuffer (黏包,半包)

  • Hello,world\nI'm zhangsan\nHo
  • w are you?\n

解决

public class TestByteBufferExam {
    public static void main(String[] args) {
        ByteBuffer source = ByteBuffer.allocate(64);
        source.put("Hello,world\nI'm zhangsan\nHo".getBytes());
        split(source);
        source.put("w are you?\nhaha!\n".getBytes());
        split(source);
    }

    private static void split(ByteBuffer buffer) {
        buffer.flip();
        for (int i = 0; i < buffer.limit(); i++) {
            if ('\n' == buffer.get(i)) {
                int length = i - buffer.position() + 1;
                ByteBuffer allocate = ByteBuffer.allocate(length);
                for (int j = 0; j < length; j++) {
                    allocate.put(buffer.get());
                }
                ByteBufferUtil.debugAll(allocate);
            }
        }
        buffer.compact();
    }
}
posted @   jpy  阅读(96)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
历史上的今天:
2021-10-12 阿里云的这群疯子
点击右上角即可分享
微信分享提示