NIO(JDK1.4)--缓冲区
来源:互联网 发布:淘宝网1 编辑:程序博客网 时间:2024/06/05 14:12
基础
1、缓冲区API:
让我们来看一下可以如何使用一个缓冲区。以下是Buffer类的方法签名:package
java.nio;
public
abstract
class
Buffer {
public
final
int
capacity( )
public
final
int
position( )
public
final
Buffer position (
int
newPositio )
public
final
int
limit( )
public
final
Buffer limit (
int
newLimit)
public
final
Buffer mark( )
public
final
Buffer reset( )
public
final
Buffer clear( )
public
final
Buffer flip( )
public
final
Buffer rewind( )
public
final
int
remaining( )
public
final
boolean
hasRemaining( )
public
abstract
boolean
isReadOnly( );
}
buffer.mark();
buffer.position(
5
);
buffer.reset();
buffer.mark().position(
5
).reset();
假如我们想把一个缓冲区传递给一个通 道,以使内容能被全部写出。但如果通道现在在缓冲区上执行 get(),那么它将从position指向的位置开始取出数据,如图1所示,而position在调用put()写入数据时会往后移动的,所以,在写出数据前,应先把position移到缓冲区的开头,但是它是怎样知道何时到达我们所插入数据末端的呢?这就是上界属性被引入的目的。上界属性指明了缓冲区有效内容的末端。我们需要将上界属性设置为当前位置,然后将位 置重置为0。我们可以人工用下面的代码实现:
buffer.limit(buffer.position()).position(
0
);
但这种从填充到释放状态的缓冲区翻转是 API 设计者预先设计好的,他们为我们提供了 一个非常便利的函数:
buffer.flip();
flip()函数将一个能够继续添加数据元素的填充状态的缓冲区翻转成一个准备读出元素 的释放状态。在翻转之后,图1的缓冲区状态会变成图2的缓冲区状态。
图1:
图2:翻转后的缓冲区
rewind()函数与flip()相似,但 rewind()不影响上界属性。它只是将位置值设回0。您可以使用rewind()后退,重读已经被翻转的缓冲区中的数据。
如果将缓冲区翻转两次会怎样呢?会把缓冲区大小变为0。比如对图2执行flip(),则 把上界设为位置的值,并把位置设为0。上界和位置都变成 0。尝试对缓冲区上位置和上界都为0的get()操作会导致BufferUnderflowException异常。而put()则会导致BufferOverflowException异常。
3、读取
如果您接收到一个在别处被填满的缓冲区,您可能需要在检索内容之前将其翻转。例如,如果一个通道的 read()操作完成,而您想要查看被通道放入缓冲区内的数据,那么您需要在调用 get()之前翻转缓冲区。通道对象在缓冲区上调用 put()增加数据;put和read可以随意混合使用。
布尔函数hasRemaining()返回是否已达到缓冲区的上界,如:
for
(
int
i =
0
; buffer.hasRemaining(), i++) {
myByteArray [i] = buffer.get();
}
int
count = buffer.remaining();
for
(
int
i =
0
; i < count, i++) {
myByteArray [i] = buffer.get();
}
例子:
package
com;
import
java.nio.CharBuffer;
public
class
test{
public
static
void
main(String [] argv)
throws
Exception{
CharBuffer buffer = CharBuffer.allocate (
100
);
while
(fillBuffer (buffer)){
buffer.flip();
drainBuffer (buffer);
buffer.clear();
}
}
private
static
void
drainBuffer (CharBuffer buffer){
while
(buffer.hasRemaining()) {
System.out.print (buffer.get());
}
System.out.println (
""
);
}
private
static
boolean
fillBuffer (CharBuffer buffer){
if
(index >= strings.length) {
return
false
;
}
String str = strings [index++];
for
(
int
i =
0
; i < str.length(); i++) {
buffer.put (str.charAt (i));
}
return
true
;
}
private
static
int
index =
0
;
private
static
String [] strings = {
"A random string value"
,
"The product of an infinite number of monkeys"
,
"Hey hey we're the Monkees"
,
"Opening act for the Monkees: Jimi Hendrix"
,
"'Scuse me while I kiss this fly"
,
"Help Me! Help Me!"
,
};
}
4、压缩
有时,您可能只想从缓冲区中释放一部分数据,而不是全部,然后继续接着填充。为了实现这 一点,未读的数据元素需要向前移至头部,当前位置position要移到下一个写入数据的位置。可以重复调用get、put方法实现(get、put方法分别有get()、get(int index)、put()、put(int index),当然还有其它参数列表类型,可以指定读写的位置),但这样做会效率低下,而API对此提供了一个compact()函数。这一缓冲区工具在复制数据时 要比使用get()和put()函数高效得多。所以当需要时,请使用compact(),下图是使用compact前后的缓冲区状态:
compact前:
compact后:
5、标记
缓冲区的标记在mark()函数被调用之前是未定义的,调用时标记被设为当前位置的值,标记的作用是:当需要的时候,可以用reset()把position设置为之前标记的位置,如果标记还没定义,调用reset()会报异常。调用 rewind()、 clear() 以及flip()函数时会导致标记被抛弃,调用limit()或position()的带参版本函数时,如果参数比当前标记小,则也会导致标记被抛弃。
如图1,调用buffer.position(2).mark().position(4);后得到图2
图1:
图2:
图2基础上调用reset(),会得到图3
图3:
java.nio.ByteBuffer中flip、rewind、clear方法的区别
对缓冲区的读写操作首先要知道缓冲区的下限、上限和当前位置。下面这些变量的值对Buffer类中的某些操作有着至关重要的作用:
clear方法将缓冲区清空,所谓的清空不是指清空缓冲区数据,仅是改变position等属性的值,一般是在重新写缓冲区之前调用,调用clear之后如果马上读缓冲区数据,则可以读出之前填入的数据,但由于limit位置被设为capacity,所以,结尾是不可意料的。
- limit:所有对Buffer读写操作都会以limit变量的值作为上限。
- position:代表对缓冲区进行读写时,当前游标的位置。
- capacity:代表缓冲区的最大容量(一般新建一个缓冲区的时候,limit的值和capacity的值默认是相等的)。
clear方法(一般是在重新写缓冲区之前调用)
public final Buffer clear()
{
position = 0; //重置当前读写位置
limit = capacity;
mark = -1; //取消标记
return this;
}
{
position = 0; //重置当前读写位置
limit = capacity;
mark = -1; //取消标记
return this;
}
clear方法将缓冲区清空,所谓的清空不是指清空缓冲区数据,仅是改变position等属性的值,一般是在重新写缓冲区之前调用,调用clear之后如果马上读缓冲区数据,则可以读出之前填入的数据,但由于limit位置被设为capacity,所以,结尾是不可意料的。
flip方法(一般是在读缓冲区之前调用,常与compact方法一起使用)
public final Buffer flip() {
limit = position;
position = 0;
mark = -1;
return this;
}
反转缓冲区。首先将限制设置为当前位置,然后将位置设置为 0。如果已定义了标记,则丢弃该标记。 常与compact方法一起使用,因为可能之前已经被读了一部分数据。通常情况下,在准备从缓冲区中读取数据时调用flip方法。limit = position;
position = 0;
mark = -1;
return this;
}
rewind方法
1public final Buffer rewind() {
2 position = 0;
3 mark = -1;
4 return this;
5}
2 position = 0;
3 mark = -1;
4 return this;
5}
如果limit本身已经指向数据的末端,则可以用该方法代替flip,如果position并不指向数据的末端,而limit指向数据末端则不可以用flip,应该用rewind。
以上三种方法均使用final修饰,java.nio.Buffer的所有子类均使用同一种flip、clear和rewind机制。 0 0
- NIO(JDK1.4)--缓冲区
- NIO(JDK1.4)--通道
- NIO(JDK1.4)--选择器Selector
- Java NIO学习4(缓冲区2)
- Java 新IO技术(NIO) JDK1.4
- java nio 缓冲区学习
- NIO - Buffer缓冲区
- NIO学习--缓冲区
- JAVA NIO 缓冲区
- NIO - Buffer缓冲区
- java nio 缓冲区(一)
- java nio 缓冲区(二)
- java nio 缓冲区基础
- Java NIO 缓冲区
- java NIO(一) 缓冲区
- java NIO(二) 缓冲区
- java NIO(三) 缓冲区
- Java NIO学习:缓冲区
- 浮点数在计算机中不能准确表示范例
- 二分图-最大匹配,最小路径覆盖,最小点覆盖(KM算法)
- 关于指针的加减操作
- Webkit中HTML5 Video的实现分析-HTMLMediaElement & MediaPlayer
- 一次mongoDB的崩溃拉起记录
- NIO(JDK1.4)--缓冲区
- 剑指offer:3-二维数组中的查找
- 理解HotSpot的CMS GC
- Objective-C中不同方式实现锁(一)
- centos7 lamp环境配置及多域名设置
- 黑马程序员 反射
- CCF 201312-1出现次数最多的数
- HDU 2689 Sort it(树状数组求逆序数)
- js 判断文件是否存在