之前看过相关的ByteBuffer的使用,但是问题是那时还年轻,所以现在有点老了,因此,忘记了,所以决心看源代码了解一番----故作此篇文章。
查看ByteBuffer的API,看的我是一头雾水,搞不清什么mark、position、limit、flip、reset几个的用法,先看下面的例子:
String str = "helloWorld";
ByteBuffer buff = ByteBuffer.wrap(str.getBytes());
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
//读取两个字节
buff.get();
buff.get();
System.out.println("position:"+ buff.get(buff.position())+"\t limit:"+buff.limit());
buff.mark();
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
buff.flip();
System.out.println("position:"+buff.position()+"\t limit:"+buff.limit());
输出结果:
position:0 limit:10
position:2 limit:10
position:2 limit:10
position:0 limit:2
我们以每位开发人员熟悉的”helloworld“,用ByteBuffer将字符串包装,由于ByteBuffer是一个抽象类,通过wrap包装的对象将实际返回的是一个HeapByteBuffer对象。由此可知HeapByteBuffer是ByteBuffer的子类,同样的ByteBuffer又是Buffer抽象类的子类。以上提到的mark、position、limit、flip、reset都是出自于Buffer这个抽象类。
下面我们来解析几个方法的,当我们调用了wrap方法后Buffer中初始化的结构是:
注释:
m:mark;
p:position;
L:limit;
初始情况下mark是指向第一个元素之前的的即-1,postion为指向第一个元素为0.而Limit是被赋值为byte[]的长度。
因此这就是打印结果的第一行。
m |
|
|
p |
|
|
|
|
|
|
|
L |
-1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
|
H |
E |
L |
L |
O |
W |
O |
R |
L |
D |
|
当我们连续调用两次get()方法获得两个个字节,每次调用都会触发position++操作,那么此时position就会移动到index = 2的的地方,而这个时候Limit和mark是不会发生变化的。如果将读取的两个字节打印会是H和E,因此执行结果第二行会有position:2 limit:10结果.
|
|
|
m、p |
|
|
|
|
|
|
|
L |
-1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
|
H |
E |
L |
L |
O |
W |
O |
R |
L |
D |
|
读取完毕后我们使用mark,这个时候mark会从-1移动到2和position指向同一个元素,可以看见Limit是不会发生改变的。
m |
p |
|
L |
|
|
|
|
|
|
|
|
-1 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
|
|
H |
E |
L |
L |
O |
W |
O |
R |
L |
D |
|
使用了mark标记的当前的position后,如果们调用flip,这个时候Limit就会指向position的位置,并将mark和position还原为初始值。这样就知道了limit当前的就为2,什么意思呢?就是说当前可以读的字节数是2。
我们可以尝试一下如下代码:
System.out.println((char)buff.get()+""+(char)buff.get());
输出结果:he
貌似这也没什么稀奇的,如果你在代码换成
// System.out.println((char)buff.get()+""+(char)buff.get()
System.out.println((char)buff.get()+""+(char)buff.get()+""+(char)buff.get());
输出结果:position:0 limit:10
Exception in thread "main" java.nio.BufferUnderflowException
at java.nio.Buffer.nextGetIndex(Buffer.java:474)
at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:117)
at com.taobao.moxing.notify.Main.main(Main.java:33)position:2 limit:10
position:2 limit:10
position:0 limit:2
为什么会抛异常呢?原因是limit的含义就想一个窗口,你当前能读到的数据就是当前窗口限制的(本例中即为2),如果这个窗口之外的所有元素都是不可读的。至此我想你和我就应该明白这几个参数的含义了吧。
而至于reset方法,它是将当前的position设置为0,
rewind是将mark重置为-1,position重置为0;
clear方法是真正的重置,将mark=-1,position=0,limit=capacity(即当前buffer的容量)
分享到:
相关推荐
使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com
仿安卓ByteBuffer 完美组包、拆包
主要介绍了Android在JNI中使用ByteBuffer的方法,涉及Android中缓冲区的相关使用技巧,需要的朋友可以参考下
Android
主要解决从流中获取数据,缓存,拆解,可用于TCP粘包问题
【IT十八掌徐培成】Java基础第26天-05.ByteBuffer-mark-pos-limit-cap-flip.zip
易语言汇编版ByteBuffer源码。主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样。@10371178。Tags:易语言汇编版ByteBuffer源码。
protobuf+long+bytebuffer,利用protobuf.js实现编解码 所需的三个js库
ios-byteBuffer [![CI状态]( Lee / ios-byteBuffer.svg?style = flat)]( Lee / ios-byteBuffer ) 用法 #分配 ByteBuffer *buffer = [ByteBuffer initWithOrder: ByteOrderLittleEndian]; #输入数据 - ( ...
java api之ByteBuffer基础、应用场景、实战讲解 文档中有丰富的例子代码实现
易语言汇编版ByteBuffer源码主要用于各种网络协议的组包 具体用法可以点上面的网址 功能和jAVA的一样
dena-bytebuffer
jdk api-ServerSocketChannel、Selector、ByteBuffer结合实现网络报文间的通讯
NULL 博文链接:https://chinaestone.iteye.com/blog/468138
NULL 博文链接:https://zheng12tian.iteye.com/blog/1094811
使用BufferedInputStream字节流,以及StringBuiler技术实现字节的逐行读取。即字节流的readline功能。BufferedInputStream bufferedInputStream=new BufferedInputStream(new FileInputStream(file));
描述:为了解决java与C结构通信过程中结构体解析问题。 主要功能:能友好的用java处理任何发送的C结构体对象,并且能发送java对象转换成C结构体接收的二进制。 ...4、配置简单,使用方便、易上手。
或在浏览器中使用: dist/byte-buffer.js dist/byte-buffer.min.js 用法 作为ECMAScript模块: import ByteBuffer from 'byte-buffer' ; const b = new ByteBuffer ( ) ; 在CommonJS环境中: const ByteBuffer...