Java NIO读书笔记之Buffer缓冲区(二)
11.创建缓冲区
创建缓冲区通常有两种方式:分配和包装
分配:CharBuffer charBuffer = CharBuffer.allocate(1000);
包装:
char[] array = new char[100];
CharBuffer charBuffer = CharBuffer.wrap(array);
public static void main(String[] args) {
char[] array = new char[100];
CharBuffer charBuffer = CharBuffer.wrap(array);
charBuffer.put('H').put('e').put('l').put('l').put('o');
for(char c : array){
if(c != '\0')
System.out.print(c);
} //Hello
array[1] = 'a';
charBuffer.flip();
for(int i = 0;i < charBuffer.limit(); i++){
System.out.print(charBuffer.get());
} //Hallo
}
通过wrap方法构建的缓冲区,改变数组的时候会改变缓冲区,改变缓冲区的时候数组同样会发生变化
wrap方法还提供了一个重载的版本:
wrap(txt, offset, length);
不过offset和length并不是取一个数组的子集,offset和length参数会初始化缓冲区的状态,position = offset, limit = offset +
length
通过allocate和wrap方法创建的缓冲区都可以获得备份数组,hasArray()可以得到缓冲区是否有一个可存取的备份数组,array()返回备份
数组的引用,如果hasArray()返回false,那么调用array()方法将会抛出UnsupportedOperationException
12.复制缓冲区
public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
public abstract CharBuffer duplicate();
public abstract CharBuffer asReadOnlyBuffer();
public abstract CharBuffer slice();
}
duplicate():
创建一个新的缓冲区,该缓冲区与原缓冲区共享数据元素,拥有同样的容量,每个缓冲区拥有各自的position、limit和mark属性,对一个
缓冲区数据的改变会映射到另一个缓冲区上,如果原缓冲区的属性为只读,那么新缓冲区的属性也是只读的。
public static void main(String[] args) {
CharBuffer charBuffer = CharBuffer.allocate(10);
charBuffer.put(new char[]{'H', 'e', 'l', 'l', 'o'});
CharBuffer charBuffer2 = charBuffer.duplicate();
System.out.println("Dup position:" + charBuffer2.position());
System.out.println("Dup limit:" + charBuffer2.limit());
System.out.println("Dup capacity:" + charBuffer2.capacity());
charBuffer2.flip();
System.out.println("Old position:" + charBuffer.position());
System.out.println("Old limit:" + charBuffer.limit());
System.out.println("Old capacity:" + charBuffer.capacity());
charBuffer2.position(2);
charBuffer2.compact();
charBuffer.flip();
for(int i = 0; i < charBuffer.limit(); i++){
System.out.print(charBuffer.get()); //llolo
}
}
asReadOnlyBuffer():
通过此方法创建一个只读的缓冲区,这个新缓冲区不允许使用put()来进行操作。
slice():
创建一个从原缓冲区当前位置开始的新缓冲区,其容量是(limit - position)这个新缓冲区与原始缓冲区共享一段数据元素子序列,分割出
来的序列也会只继承可读属性。
13.直接缓冲区:
直接缓冲区被用于与通道和固有IO例程的交互,它们通过使用固有代码来告知操作系统直接释放或填充内存区域。只有ByteBuffer类型的缓
冲区才能够被创建为直接缓冲区类型:
ByteBuffer byteBuffer = ByteBuffer.allocateDirect();
另外所有的缓冲区都提供了一个isDirect()的方法来判断该缓冲区是否是直接缓冲区。
public static void main(String[] args){
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
System.out.println(byteBuffer.isDirect()); //false
byteBuffer = ByteBuffer.allocateDirect(10);
System.out.println(byteBuffer.isDirect()); //true
}
14.视图缓冲区:
视图缓冲区通过已存在的缓冲区对象实例的工厂方法来创建,这种视图对象维护它自己的属性,容量,位置,上界和标记。但是和原来的缓冲区共享数据。
public abstract class ByteBuffer
extends Buffer implements Comparable{
public abstract CharBuffer asCharBuffer();
public abstract ShortBuffer asShortBuffer();
public abstract IntBuffer asIntBuffer();
public abstract LongBuffer asLongBuffer();
public abstract FloatBuffer asFloatBuffer();
public abstract DoubleBuffer asDoubleBuffer();
}
15.数据元素视图:
ByteBuffer采取了一种轻量机制,可以将字节组合为多字节的数据类型来存取
ByteBuffer byteBuffer = ByteBuffer.allocate(10);
int value = byteBuffer.getInt(); //取得整形值
getInt方法将会取当前position开始的4个字节,并将其包装成int