您的位置:首页 > Web前端

NIO学习笔记——Buffer的创建与复制

2017-06-21 21:07 169 查看

Buffer的创建

新的缓冲区是由分配或包装操作创建的。分配操作创建一个缓冲区对象并分配一个私有的空间来储存容量大小的数据元素。包装操作创建一个缓冲区对象但是不分配任何空间来储存数据元素。它使用您所提供的数组作为存储空间来储存缓冲区中的数据元素,例如

CharBuffer charBuffer = CharBuffer.allocate (100);


这段代码隐含地从堆空间中分配了一个 char 型数组作为备份存储器来储存 100 个 char变量。如果您想提供您自己的数组用做缓冲区的备份存储器,请调用 wrap()函数

char [] myArray = new char [100];
CharBuffer charbuffer = CharBuffer.wrap (myArray);


这段代码构造了一个新的缓冲区对象,但数据元素会存在于数组中。这意味着通过调用put()函数造成的对缓冲区的改动会直接影响这个数组,而且对这个数组的任何改动也会对这个缓冲区对象可见。带有 offset 和 length 作为参数的 wrap()函数版本则会构造一个按照您提供的 offset 和 length参数值初始化位置和上界的缓冲区。这样做:

CharBuffer charbuffer = CharBuffer.wrap (myArray, 12, 42);


创建了一个 position 值为 12, limit 值为 54,容量为 myArray.length 的缓冲区。

我们用来做例子的CharBuffer 提供了一对其它缓冲区类没有的有用的便捷的函数

public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
// This is a partial API listing38
public static CharBuffer wrap (CharSequence csq)
public static CharBuffer wrap (CharSequence csq, int start,
int end)
}


Wrap()函数创建一个只读的备份存储区是 CharSequence 接口或者其实现的的缓冲区对象charsequence 描述了一个可读的字符流

CharBuffer charBuffer = CharBuffer.wrap ("Hello World");


三个参数的 wrap()函数版本使用 start 和 end 下标参数来描述传入的 CharSequence对象的子序列。这是一个方便的类似于调用了 CharSequence.subsequence()函数的转

换。 Start 参数是序列中使用的第一个字符, end 是最后一个字符的下标值加 1

Buffer的复制

当一个管理其他缓冲器所包含的数据元素的缓冲器被创建时,这个缓冲器被称为视图缓冲器。视图存储器总是通过调用已存在的存储器实例中的函数来创建。使用已存在的存储器实例中的工厂方法意味着视图对象为原始存储器的内部实现细节私有。数据元素可以直接存取,无论它们是存储在数组中还是以一些其他的方式,而不需经过原始缓冲区对象的 get()/put()API。

我们以 CharBuffer 为例,同样的操作可被用于任何基本的缓冲区类型

public abstract class CharBuffer
extends Buffer implements CharSequence, Comparable
{
// This is a partial API listing
public abstract CharBuffer duplicate( );
public abstract CharBuffer asReadOnlyBuffer( );
public abstract CharBuffer slice( );
}


Duplicate()函数创建了一个与原始缓冲区相似的新缓冲区。两个缓冲区共享数据元39素,拥有同样的容量,但每个缓冲区拥有各自的位置,上界和标记属性。对一个缓冲区内的数据元素所做的改变会反映在另外一个缓冲区上。这一副本缓冲区具有与原始缓冲区同样的数据视图。如果原始的缓冲区为只读,或者为直接缓冲区,新的缓冲区将继承这些属性。复制一个缓冲区会创建一个新的 Buffer 对象,但并不复制数据。原始缓冲区和副本都会操作同样的数据元素。

我们可以使用asReadOnlyBuffer()函数来生成一个只读的缓冲视图。这与duplicate()相同,除了这个新的缓冲区不允许使用 put(),并且其 isReadOnly()函数将会返回true。 对这一只读缓冲区的put()函数的调用尝试会导致抛出ReadOnlyBufferException 异常。

如果一个只读的缓冲区与一个可写的缓冲区共享数据,或者有包装好的备份数组,那么对这个可写的缓冲区或直接对这个数组的改变将反映在所有关联的缓冲区上,包括只读缓冲区

分割缓冲区与复制相似,但 slice()创建一个从原始缓冲区的当前位置开始的新缓冲区,并且其容量是原始缓冲区的剩余元素数量( limit-position)。这个新缓冲区与原始缓冲区共享一段数据元素子序列。分割出来的缓冲区也会继承只读和直接属性。

CharBuffer buffer = CharBuffer.allocate (8);
buffer.position(3).limit (5);
CharBuffer sliceBuffer = buffer.slice();


要创建一个映射到数组位置 12-20( 9 个元素)的 buffer 对象

char [] myBuffer = new char [100];
CharBuffer cb = CharBuffer.wrap(myBuffer);
cb.position(12).limit(21);
CharBuffer sliced = cb.slice();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: