Java NIO的核心部件:
Buffer
Channel
Selector
Buffer
是一个数组,但具有内部状态。如下4个索引:
- capacity:总容量
- position:下一个要读取/写入的元素索引
- limit:限制,第一个不能读取/写入的元素索引
- mark:位置标记,重置position
- //通过调用Buffer.mark()方法,可以标记Buffer中的一个特定position。之后可以通过调用Buffer.reset()方法恢复到这个position//
- 0 <= mark <= position <= limit <= capacity
用例:
初始状态:
初始如上图,添加数据:put()方法会改变position的值,但put(int,object)不会改变
buffer.put((byte) H).put((byte) e).put((byte) l).put((byte) l).put((byte) o);
在上图的基础上进行flip()操作,则会进入下面的状态:
flip:将缓冲区准备为数据传出状态,即limit=position,position=0
在上图基础上,进行get操作,position会后移,知道position=limit,如下图:
在上图基础上,进行rewind()的操作,position为0,limit不变,如下图,如需多次读取缓冲区数据,可以在两次读取之间使用rewind()。
假设新的状态如下图:
在新状态下进行compact()操作,进入下面状态
在新状态下进行clear()操作,返回到初始状态,即position=0,limit=capacity
Buffer的类型:
- ByteBuffer
- MappedByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
Buffer的分配:工厂方法
1、allocate
//申请48字节
ByteBuffer buf = ByteBuffer.allocate(
48
);
//申请1024字符
CharBuffer buf = CharBuffer.allocate(
1024
);
2、wrap,包装一个已有的数组
char [] myArray = new char [100];
CharBuffer charbuffer = CharBuffer.wrap (myArray);注意,这样的方式创建的Buffer,将不会在堆上创建新的数组,而是直接利用myArray做backing store,这意味着任何对myArray或者buffer的修改都将影响到buffer或者myArray。
3、复制Buffer:“浅拷贝”
- a)通过duplicate()方法将返回一个新创建的buffer,这个新buffer与原来的Buffer共享数据,一样的capacity,但是有自己的position、limit和mark属性。
- b)通过asReadOnlyBuffer()方法复制的buffer与duplicate()类似,是只读的,不能调用put。
- c)slice()方法,故名思议,类似切割一个Buffer出来,与duplicate类似,但是它将从原来Buffer的当前position开始,并且capacity等于原来Buffer的剩余元素数目,也就是(limit-position)。
向Buffer写数据
从channel写入到Buffer
int
bytesRead = inChannel.read(buf);
通过Buffer的put方法写入
buf.put(127);
相对位置:在position之后写入数据,并改变position
put(byte b);
put(byte[] src);
put(byte[] src, int offset, int length);
put(ByteBuffer src);
绝对位置:提供写入的位置,并不改变position值。
put(int index, byte b);
从Buffer读数据
从channel读出数据
int
bytesWritten = inChannel.write(buf);
通过Buffer的get方法
相对位置
get()
get
(byte[] dst);
get
(byte[] dst, int offset, int length);
绝对位置
get(int index);