java.nio.ByteBuffer用法实际操作,没有理论全是举例练习

通过测试理解各种方法的用法

test1

ByteBuffer buffer = ByteBuffer.allocate(8);

byte[] temp = new byte[] {
    
    3, 2, 1};

// 写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
System.out.println("写入数据之前 : " + buffer);

// 写入字节数组到缓存
buffer.put(temp);

// 写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
System.out.println("写入数据之后 : " + buffer);

// 重置游标
buffer.flip();

// 重置游标之后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]
System.out.println("重置游标之后 : " + buffer);

for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}


写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
重置游标之后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]
0 - 3
1 - 2
2 - 1
概念解释:
position       limit          capacity
pos - 游标位置, lim - 限制数量, cap - 最大容量

上文出现的方法:
buffer.put(temp);    容易理解
buffer.flip();       参看下文  flip 是重置游标 : lim = pos (把 pos 赋值给 lim) ; pos = 0;  我理解就是为取值做准备;
buffer.remaining()   参看下文  remaining = lim - pos
buffer.get(i)        容易理解 

test2

ByteBuffer buffer = ByteBuffer.allocate(8);

byte[] temp = new byte[] {
    
    3, 2, 1};

// 写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
System.out.println("写入数据之前 : " + buffer);
buffer.put(temp);
// 写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
System.out.println("写入数据之后 : " + buffer);

for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}


写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
0 - 3
1 - 2
2 - 1
3 - 0
4 - 0
上例子结果验证 remaining = lim - pos  即 8-3=5

[3,2,1,0,0,0,0,0]
for (int i = 0; i < 5; i++)

所以会输出 3,2,1,0,0

test3

ByteBuffer buffer = ByteBuffer.allocate(8);
byte[] temp = new byte[] {
    
    3, 2, 1};
System.out.println("写入数据之前 : " + buffer);
buffer.put(temp);
System.out.println("写入数据之后 : " + buffer);
System.out.println(buffer.get());

结果:
0
分析
[3,2,1,0,0,0,0,0]
       ↑
此时游标的位置,所以是0
------------------------------------------------------------------------------------------
ByteBuffer buffer = ByteBuffer.allocate(8);
byte[] temp = new byte[] {
    
    3, 2, 1};
System.out.println("写入数据之前 : " + buffer);
buffer.put(temp);
System.out.println("写入数据之后 : " + buffer);
buffer.flip();
for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}
		
结果	:
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
0 - 3
1 - 2
2 - 1
分析:
flip: lim = pos,pos=0;
remaining = lim - pos 即 3-0=3
for (int i = 0; i < 3; i++)

[3,2,1,0,0,0,0,0]
 ↑ ↑ ↑    
所以游标取值如上为 3,21
------------------------------------------------------------------------------------------
ByteBuffer buffer = ByteBuffer.allocate(8);

byte[] temp = new byte[] {
    
    3, 2, 1};
System.out.println("写入数据之前 : " + buffer);

buffer.put(temp);
System.out.println("写入数据之后 : " + buffer);
for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}
System.out.println("-------- ");

buffer.flip();
System.out.println("flip 后 : " + buffer);
for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}
System.out.println("-------- ");

System.out.println(buffer.get());
System.out.println("get 后 : " + buffer);
System.out.println("-------- ");
for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}

结果:
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
0 - 3
1 - 2
2 - 1
3 - 0
4 - 0
-------- 
flip 后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]
0 - 3
1 - 2
2 - 1
-------- 
3
get 后 : java.nio.HeapByteBuffer[pos=1 lim=3 cap=8]
-------- 
0 - 3
1 - 2

分析:
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
[0,0,0,0,0,0,0,0]	
 ↑        	     ●
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
[3,2,1,0,0,0,0,0]
       ↑         ●
第一个打印:
remaining = 8-3=5
for (int i = 0; i < 5; i++) 
所以是 3,2,10,0

buffer.flip();
flip 后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]
[3,2,1,0,0,0,0,0]
 ↑     ●
第二次打印:
remaining = 3-0=3
for (int i = 0; i < 3; i++) 
所以是 3,2,1

buffer.get() 取出第一个值,游标自动往后挪一位; 所以结果是3
[3,2,1,0,0,0,0,0]
   ↑   ●
get 后 : java.nio.HeapByteBuffer[pos=1 lim=3 cap=8]

第三次打印:
remaining = 3-1=2
for (int i = 0; i < 3; i++) 
所以结果是 3,2


总结一点就是:flip + remaining 一起使用就是把缓存的内容输出;这个组合是最有意义的
buffer.flip();
for (int i = 0; i < buffer.remaining(); i++) {
    
    
    int data = buffer.get(i);
    System.out.println(i + " - " + data);
}
缓存为 [3,2,1,0,0,0,0,0]  输出结果为:3,2,1

test4

ByteBuffer buffer = ByteBuffer.allocate(8);
byte[] temp = new byte[] {
    
    3, 2, 1};
System.out.println("写入数据之前 : " + buffer);
buffer.put(temp);
System.out.println("写入数据之后 : " + buffer);

buffer.flip();
buffer.flip();

System.out.println(buffer.get());

结果:
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]

java.nio.BufferUnderflowException
	at java.nio.Buffer.nextGetIndex(Buffer.java:500)
	at java.nio.HeapByteBuffer.get(HeapByteBuffer.java:135)

分析:
[3,2,1,0,0,0,0,0]
       ↑
第一个flip以后: lim = pos,pos=0; lim = 3 , pos = 0;
[3,2,1,0,0,0,0,0]
 ↑     ●
 第二个flip以后: lim = pos,pos=0;lim = 0 , pos = 0;
  [3,2,1,0,0,0,0,0]
●  ↑     
get() -> 获取当前游标指向的位置的数据;此时游标是0指的是第一项,但是此时lim为0表示啥也没有,所以取值会报错

test5

ByteBuffer buffer = ByteBuffer.allocate(8);
byte[] temp = new byte[] {
    
    3, 2, 1};
System.out.println("写入数据之前 : " + buffer);
buffer.put(temp);
System.out.println("写入数据之后 : " + buffer);

buffer.flip();
System.out.println("写入数据之后 : " + buffer);

buffer.clear();
System.out.println("写入数据之后 : " + buffer);

buffer.put((byte) 10);
buffer.put((byte) 11);
System.out.println("写入数据之后 : " + buffer);

------------------------------------------------------------------------------------------
结果:
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
写入数据之后 : java.nio.HeapByteBuffer[pos=2 lim=8 cap=8]

------------------------------------------------------------------------------------------

新方法:
clear();  position = 0; limit = capacity;

------------------------------------------------------------------------------------------

分析:
ByteBuffer.allocate(8);
写入数据之前 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
[0,0,0,0,0,0,0,0]
 ↑               ●
byte[] temp = new byte[] {
    
    3, 2, 1};
写入数据之后 : java.nio.HeapByteBuffer[pos=3 lim=8 cap=8]
[3,2,1,0,0,0,0,0]
       ↑         ●
buffer.flip();
写入数据之后 : java.nio.HeapByteBuffer[pos=0 lim=3 cap=8]  
[3,2,1,0,0,0,0,0]     
 ↑     ●
 buffer.clear();
写入数据之后 : java.nio.HeapByteBuffer[pos=0 lim=8 cap=8]
[3,2,1,0,0,0,0,0]     
 ↑               ●
注意:此时get()还能取到3;再往里添加值回去覆盖原来的值

buffer.put((byte) 10);
[10,2,1,0,0,0,0,0]     
    ↑             ●
buffer.put((byte) 11);
[10,11,1,0,0,0,0,0]     
       ↑           ●
写入数据之后 : java.nio.HeapByteBuffer[pos=2 lim=8 cap=8]

Buffer的应用固定逻辑

写操作顺序

假如原来存储的内容
[10,2,1,0,0,0,0,0]     
    ↑             ●
1. clear() 
[10,2,1,0,0,0,0,0]     
 ↑                ●
2. put() -> 写操作 :假设写入1,2,3,4
[1,2,3,4,0,0,0,0]     
         ↑       ●
3. flip() -> 重置游标 
[1,2,3,4,0,0,0,0]     
 ↑       ●
4. SocketChannel.write(buffer); -> 将缓存数据发送到网络的另一端 
5. clear()
[1,2,3,4,0,0,0,0]     
 ↑               ●

读操作顺序

假如原来存储的内容
[10,2,1,0,0,0,0,0]     
    ↑             ●
1. clear() 
[10,2,1,0,0,0,0,0]     
 ↑                ●
2. SocketChannel.read(buffer); -> 从网络中读取数据 假如读进来1,2,3,4
[1,2,3,4,0,0,0,0]     
 ↑               ●
3. buffer.flip() -> 重置游标 
[1,2,3,4,0,0,0,0]     
 ↑       ●
4. buffer.get() -> 读取数据 
[1,2,3,4,0,0,0,0]     
 ↑ ↑ ↑ ↑ ●
5. buffer.clear()
[1,2,3,4,0,0,0,0]     
 ↑               ●

猜你喜欢

转载自blog.csdn.net/weixin_37646636/article/details/120555434