1,buffer
缓冲区成员:
private int mark = -1;//一个备忘位置,调用mark()方法时,mark = position;调用reset()方法时,position=mask;
private int position = 0;//位置,下一个要被读取或写的元素的索引,位置会自动由相应的get(),put()函数更新。
private int limit;//上界,缓冲区第一个不能被读取或写的元素。或者说缓冲区中现存元素的计数,或者代表有效数据的末端
private int capacity;//容量,在缓冲区被创建时设定,且永远不能被改变
long address;
buffer中遵循这样的关系:
0<= mark <= position <=limit <=capacity
填充:
现在将hello填充到buffer:
b.put((byte)'H').put((byte)'e').put((byte)'l').put((byte)'l').put((byte)'0');
修改:将原来的Hello,修改为Mellow
b.put(0,(byte)'M').put((byte)'w');
翻转:
我们已经写满了缓冲区,现在我们必须将其清空,我们想把这个缓冲区传递给一个通道,以使内容全部被写出,我们可以人工实现代码
b.limit(b.position()).position(0);
或者直接调用
b.flip();
flip()用于翻转缓冲区,翻转后的效果图为:翻转后的缓冲区无法写入,只能读取
下面代码是将数据元素从数据缓冲区释放到一个数组:
int count = buffer.hasRemaining();
for (int i = 0; i<count; i++) {
myByteArray [i] = buffer.get( );
}
值得注意的是:缓冲区不是线程安全的,在需要并发操作时,需要先同步
使用b.clear()可以将缓冲区重置为空状态
下面是一个练习缓冲区的例子
package com.asdc.webservice;
import java.nio.CharBuffer;
public class BufferFillDrain {
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", // Sorry Jimi ;-)
"Help Me! Help Me!",
};
public static void main(String[] args) {
CharBuffer charBuffer = CharBuffer.allocate(100);
//当判断为true,则可以翻转这个数组
while(fillBuffer(charBuffer)){
charBuffer.flip();//翻转缓冲区
drainBuffer(charBuffer);
charBuffer.clear();//清空缓冲区
}
}
private static void drainBuffer(CharBuffer charBuffer) {
char [] smallArr = new char[10];
while(charBuffer.hasRemaining()){
int len = Math.min(charBuffer.remaining(), smallArr.length);
charBuffer.get(smallArr, 0, len);
}
System.out.println("");
}
private static boolean fillBuffer(CharBuffer charBuffer) {
if(index>=strings.length){
//不填充
return false;
}
String string = strings[index++];
while(charBuffer.remaining()>string.length()){
charBuffer.put(string);//等价于charBuffer.put(string,0,string.length());
}
return true;
}
}
压缩缓冲区:
buffer.compact()
调用compact()方法是丢弃已经释放掉的数据,保留未释放的数据,并使缓冲区对重新填充容量准备就绪
压缩前的缓冲区:压缩后的缓冲区:
标记:使缓冲区能记住一个位置并在之后返回
调用mark()时,将当前位置作为标记
调用reset()时,返回到之前标记的地方
注意:1,rewind( ),clear( ),flip( )总是丢弃标记
2,如果新设定的值小于当前的值,调用limit( )和position( )带有索引参数的版本会抛弃标记
执行下面代码后:设定标记为2
buffer.position(2).mark().position(4);
如果此时将缓冲区传递给管道,则“ow”将被发送,而且position会前进到6
如果此时调用reset( );则position后退到2,若此时将缓冲区传递给管道,这"llow"将被发送,而且position会前进到6
相等:
判断两个缓冲区相等的充要条件是:
1,两个对象类型相同
2,两个缓冲区剩余同样数量的元素
3,每个缓冲区被get( )函数返回的数据元素序列必须一致
//缓冲区复制
CharBuffer buffer = CharBuffer.allocate(10);
buffer.position(3).limit(6).mark().position(5);
CharBuffer duBuffer = buffer.duplicate();
buffer.clear();
//缓冲区分割
char [] myBuff = new char[100];
CharBuffer cb = CharBuffer.wrap(myBuff);
cb.position(12).limit(21);
CharBuffer sliceBuffer = cb.slice();