目录
目标
常用API
工具方法
演示案例
allocate(int capacity)和allocateDirect(int capacity)
put()和get()
flip()和hasRemaining()
clear()
compact()
wrap()
总结
掌握ByteBuffer常用方法,分析ByteBuffer对象在切换读写模式的情况下基本属性的变化情况。
方法 | 描述 | 案例 |
allocate(int capacity) | 分配capacity个字节的缓冲区。返回HeapByteBuffer对象,即jdk内存堆字节缓冲区。 | ByteBuffer buffer = ByteBuffer.allocate(8); |
allocateDirect(int capacity) | 分配capacity个字节的缓冲区。返回DirectByteBuffer对象,即直接内存字节缓冲区。 | ByteBuffer buffer = ByteBuffer.allocateDirect(8); |
compact() | 将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。 | buffer.compact(); |
get() | 从ByteBuffer中读取1个字节,并将position向后移动1位。 | buffer.get(); |
get(int index) | 根据index获取指定位置的字节,不会移动position。 | buffer.get(1); |
put(byte[] src) | 向ByteBuffer写字节数组数据。 | buffer.put(new byte[]{'1','a'}); buffer.put("1a".getBytes()); |
put(byte b) | 向ByteBuffer写字节数据。 | buffer.put((byte)127); |
wrap(byte[] array) | 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。 新缓冲区的大小和limit为字节数组的长度。 |
ByteBuffer.wrap("Hello World.".getBytes()); |
flip() | 将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。 | buffer.flip(); |
clear() | 将position设置为0,limit设置为capacity,mark被丢弃。 | buffer.clear(); |
capacity() | 获取ByteBuffer的容量大小。 | buffer.capacity(); |
hasRemaining() | position和limit之间是否有任何元素。 | buffer.hasRemaining(); |
public void bufferDetails(ByteBuffer buffer) {
System.out.print("position="+buffer.position());
System.out.print(";limit="+buffer.limit());
System.out.println(";capacity="+buffer.capacity());
//读取数据不移动索引。
for (int i = 0; i < buffer.limit(); i++) {
System.out.print(buffer.get(i));
System.out.print(" ");
}
System.out.println("\n");
}
/**
* JVM堆内存字节缓冲区
* 直接内存字节缓冲区
*/
public void allocateTest(){
ByteBuffer buffer = ByteBuffer.allocate(8);
//是否是直接直接内存字节缓冲区
System.out.println(buffer.isDirect());
ByteBuffer buffer2 = ByteBuffer.allocateDirect(8);
//是否是直接直接内存字节缓冲区
System.out.println(buffer2.isDirect());
}
/**
* 从ByteBuffer中读取1个字节,并将position向后移动1位。
*/
public void getAndPutTest(){
ByteBuffer buffer = ByteBuffer.allocateDirect(20);
//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
buffer.put("Hello World !".getBytes());
//切换到读模式
buffer.flip();
//position=0
System.out.println(buffer.position());
//输出72,ASCII表中H就是72
System.out.println(buffer.get());
//position=1
System.out.println(buffer.position());
//继续读取字节缓冲区返回position=1位置的数据,即返回e。
System.out.println((char)buffer.get());
}
/**
* flip():将ByteBuffer切换到读模式,position设置为0,limit设置为ByteBuffer内最后1个字节所在的索引数。
* hasRemaining() position和limit之间是否有任何元素。
*/
public void flipTest() {
ByteBuffer buffer = ByteBuffer.allocateDirect(16);
//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
buffer.put("123456789".getBytes());
bufferDetails(buffer);
//切换到读模式
buffer.flip();
bufferDetails(buffer);
//读取数据并移动position。
while(buffer.hasRemaining()){
System.out.println(buffer.get());
}
//position=9。
bufferDetails(buffer);
}
打印结果
/**
* clear():将position设置为0,limit设置为capacity,mark被丢弃。
*/
public void clearTest() {
ByteBuffer buffer = ByteBuffer.allocateDirect(16);
//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
buffer.put("123456789".getBytes());
//切换到读模式
buffer.flip();
//读取数据并移动position。
while(buffer.hasRemaining()){
buffer.get();
}
//position=9。
bufferDetails(buffer);
//position=0;limit=16;capacity=16
buffer.clear();
bufferDetails(buffer);
}
打印结果
/**
* compact():将ByteBuffer切换到写入模式,从position处将缓冲区的字节移动到起始位置。
*/
public void compactTest(){
ByteBuffer buffer = ByteBuffer.allocateDirect(16);
//注意:这里写入的字节数据size不可以超过ByteBuffer的容量,否则报错。
buffer.put("123456789".getBytes());
//切换到读模式
buffer.flip();
//读取1个字节。此时的buffer为:position=1;limit=9;capacity=16
buffer.get();
buffer.compact();
bufferDetails(buffer);
//切换到读模式
buffer.flip();
//position=0;limit=8;capacity=16,由此打印证明最后一个9不会被重复读取。
bufferDetails(buffer);
}
打印结果
/**
* 向ByteBuffer写字节数组数据。对缓冲区的修改将导致数组被修改,反之亦然。
* 新缓冲区的大小和limit为字节数组的长度。
*/
public void wrapTest(){
byte[] bytes = "123456789".getBytes();
ByteBuffer buffer = ByteBuffer.wrap(bytes);
bufferDetails(buffer);
buffer.get();
buffer.compact();
bufferDetails(buffer);
//打印234567899,证明了我们对ByteBuffer操作影响了byte[]数组。
System.out.println(new String(bytes));
bytes[2]='a';
//打印了50 51 97 53 54 55 56 57 57,证明了我们对byte[]数组操作影响了ByteBuffer。
bufferDetails(buffer);
}
打印结果
区分读模式和写模式的标准在于limit属性,如果ByteBuffer存在剩余空间,则: