赞
踩
从JDK1.4开始,java提供了一系列改进的IO处理(NIO:New IO),NIO可以替代标准的Java IO API,并且与标准的IO工作方式不同。
Java NIO 是一种同步非阻塞式IO。
Java中与新IO相关的包如下:
➢ java.nio包:主要包含各种与Buffer相关的类。
➢ java.nio.channels包:主要包含与Channel和Selector相关的类。
➢ java.nio.charset包:主要包含与字符集相关的类。
➢ java.nio.channels.spi包:主要包含与Channel相关的服务提供者编程接口。
➢ java.nio.charset.spi包:包含与字符集相关的服务提供者编程接口。
New IO中的三个核心对象:Channel(通道)和Buffer(缓冲);
- Channel是对传统的输入/输出系统的模拟,在新IO系统中所有的数据都需要通过通道传输;
- Buffer可以被理解成一个容器,它的本质是一个数组,发送到Channel中的所有对象都必须首先放到Buffer中,而从Channel中读取的数据也必须先放到Buffer中。
New IO提供了支持非阻塞式输入/输出的Selector(选择器)类;
选择器是一个可以监视多个事件通道的对象(例如:连接打开、数据到达等)。因此,单个线程可以监视多个通道的数据。
其余的组件,如 Pipe
和FileLock
只是与三个核心组件结合使用的实用程序类。
Buffer是一个抽象类。
Buffer就像一个数组,它可以保存多个类型相同的数据,可以在底层字节数组上进行get/set操作。
Buffer的类型:
CharBuffer
byteBuffer(最常用,但也与其他Buffer有点不同)
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
(boolean类型没有对应的Buffer)
这些Buffer类都没有提供构造器,通过使用如下方法来得到一个Buffer对象。
static XxxBuffer allocate(int capacity):创建一个容量为capacity的XxxBuffer对象。(不同Buffer都有的类方法)
Buffer中有三个重要的属性:容量(capacity)、界限(limit)和位置(position)。
容量:Buffer相当于一个内存块,而容量就是这个内存块所能存储的该类型元素的数量,言外之意就是这个内存块的大小,容量不为负数且创建之后大小不能改变。
界限:第一个不应该被读出或者写入的缓冲区的元素的位置索引。也就是说,位于limit后的数据既不可被读,也不可被写。限制永不为负数也永远不会大于容量。
位置:用于指明下一个可以被读出的或者写入的缓冲区位置索引(类似于IO流中的记录指针)。说明在position之前的缓冲区已经被使用,从position开始到limit之间的缓冲区未被使用。位置也永不为负数也永远不大于其界限。
0 <= mark <= position <= limit <= capacity
0-capacity:Buffer的空间大小
0-limit:表示Buffer中可以使用的空间大小
0-position:表示Buffer中已使用的空间大小
position-limit:表示buffer中可以使用但尚未使用的空间大小
(这里的大小指的是该Buffer对应的类型元素的数量;Buffer里还支持一个可选的标记(mark,类似于传统IO流中的mark),Buffer允许直接将position定位到该mark处。)
Buffer的主要作用就是装入数据,然后输出数据。
创建Buffer:
//创建大小为48个byte元素大小的ByteBuffer,capacity为48 ByteBuffer buf = ByteBuffer.allocate(48); //从通道中映射一个大小为1024个char元素大小的CharBuffer,capacity为1024 CharBuffer buf = CharBuffer.allocate(1024);使用Buffer通常遵循4个步骤:
1、数据装入Buffer
开始时:Buffer的position为0,limit为capacity,程序可通过put()方法向Buffer中放入一些数据(或者从Channel中获取一些数据),每放入一些数据,Buffer的position相应地向后移动一些位置。
2、调用Buffer的flip()方法
该方法将limit设置为position所在位置,并将position设为0,这就使得Buffer的读写指针又移到了开始位置。也就是说,Buffer调用flip()方法之后,Buffer为输出数据做好准备。
3、读取数据
使用get()系列的方法读取数据。
4、调用Buffer的clear()方法或者compact()方法,为再次向Buffer中装入数据做好准备
clear()
方法清除(注意:这里的清除并不是字面意思)整个缓冲区,clear()方法不是清空Buffer的数据,它仅仅将position置为0,将limit置为capacity,这样为再次向Buffer中装入数据做好准备。
compact()
方法仅清除(注意:这里的清除并不是字面意思)已读取的数据。任何未读数据都被移到缓冲区的开头,数据将在未读数据之后写入缓冲区。
Buffer中一些常用的方法(不完全):
➢ int capacity():返回Buffer的capacity大小。
➢ boolean hasRemaining():判断当前位置(position)和界限(limit)之间是否还有元素可供处理。
➢ int limit():返回Buffer的界限(limit)的位置。
➢ Buffer limit(int newLt):重新设置界限(limit)的值,并返回一个具有新的limit的缓冲区对象。
➢ Buffer mark():设置Buffer的mark位置,它只能在0和位置(position)之间做mark。
➢ int position():返回Buffer中的position值。
➢ Buffer position(int newPs):设置Buffer的position,并返回position被修改后的Buffer对象。
➢ int remaining():返回当前位置和界限(limit)之间的元素个数。
➢ Buffer reset():将位置(position)转到mark所在的位置。
➢ Buffer rewind():将位置(position)设置成0,取消设置的mark。Buffer的所有子类还提供了两个重要的方法:put()和get()方法,用于向Buffer中放入数据和从Buffer中取出数据。当使用put()和get()方法放入、取出数据时,Buffer既支持对单个数据的访问,也支持对批量数据的访问(以数组作为参数)。
注意:
使用put()和get()来访问Buffer中的数据时,分为相对和绝对两种。
➢ 相对(Relative):从Buffer的当前position处开始读取或写入数据,然后将位置(position)的值按处理元素的个数增加。(直接get())➢ 绝对(Absolute):直接根据索引向Buffer中读取或写入数据,使用绝对方式访问Buffer里的数据时,并不会影响位置(position)的值。(get(int index),需要给出索引值index)
equals() 和 compareTo() :
equals()
和compareTo()方法是用于比较两个缓冲区。
equals() 如果满足以下条件,则两个缓冲区相等:
- 它们的类型相同(字节、字符、整数等)
- 它们在缓冲区中具有相同数量的剩余字节、字符等(position要在相同的位置)。
- 所有剩余的字节、字符等都是相等的(position位置之后上的每一个元素也要相同)。
compareTo() 方法比较两个缓冲区的剩余元素(字节、字符等)
注意:在以下情况下,缓冲区被认为比另一个缓冲区“小”:
- 依次比较剩余元素的大小,直至元素不相等,直接返回比较结果。
- 如果所有元素都是相等的,但第一个缓冲区在第二个缓冲区之前用完元素(它有更少的元素),那么第一个缓冲区小于第二个缓冲区。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。