Java NIO 笔记
Java Nio相关的包
- java.nio:包含各种与Buffer相关的类
- java.nio.channels:包含各种与Channel和Selector相关的类
- Java.nio.charset:包含与字符集相关的类
- java.nio.channels.spi:包含于Channel相关的服务提供者编程接口
- java.nio.charset.spi:包含与字符集相关的服务提供者编程接口
Channel与Buffer详解
Channel与Buffer是nio中的两个核心对象
Channel简介
Channel是对传统的输入/输出系统的模拟,在新IO系统中所有的数据都需要通过通道传输。
Channel与传统的InputStream、OutputStream最大的区别在于它提供了一个map()方法,
通过该map()方法可以直接将“一块数据”映射到内存中。
Channel是双向的通道,而传统的输入流和输出流是单向的。
如果说传统的输入输出系统是面向流的处理,则新的IO则是面向块的处理。
Buffer简介
Buffer可以被理解成一个容器,它的本质是一个数组,发送到Channel中的所有对象都必须首先放到Buffer中,而Channel中读取的数据也必须先放到Buffer中。
除了Channel和Buffer之外,新IO还提供了用于Unicode字符串映射成字节序列以及逆映射操作的Charset类,还提供了用于支持费阻塞是输入输出的Selector类.
使用Buffer
从内部结构上来看,Buffer就像一个数组,可以保存多个类型相同的数据。Buffer是一个抽象类,其最常用的子类是ByteBuffer,它可以在底层字节数组上进行get/set操作。
除了ByteBuffer之外,对应于其他基本数据类型(boolean)都有相应的Buffer类: CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer
上面这些Buffer类,除了ByteBuffer之外,他们都采用相同或相似的方法来管理数据,只是各自管理的数据类型不同而已.
这些Buffer类都没有提供构造器,创建他们的实例的方法是:
* static XxxBuffer allocate(int capacity)创建一个容量为capacity的XxxBuffer对象
使用较多的是ByteBuffer和CharBuffer,其他Buffer子类较少用到.
其中ByteBuffer类还有一个子类:MapppedByteBuffer,用于表示Channel将磁盘文件的部分或全部内容映射到内存中后得到的结果,通常MappedByteBuffer对象由Channel的map()方法返回。
在Buffer中有三个重要概念:capicity,limit,position和两个方法:flip()和clear()
- capacity:缓冲区容量,该值不能为负数,缓冲区创建后不可修改
- limit:界限,表示limit后的区域不可读也不可写,position不能往limit后的方向移动
- position:指明下一个可以被读或写的缓冲区位置索引
- flip():将limit设置为position所在位置,并将position设置为0,为输出Buffer中已经有的数据做好准备
- clear():将limit设置为capacity,将position设置为0,为再次往Buffer中输入数据做好准备
此外Buffer还支持mark,允许position直接定位到mark处。mark的值只能在0和position之间。
Buffer包含的常用的方法
- int capacity(): 返回Buffer的capacity大小
- boolean hasRemaining(): 判断position到limit之间是否还有元素供处理
- int remainning():返回当前位置
- int limit():返回Buffer的界限的位置
- Buffer limit(int nweLt):重新设置界限(limit)的值,并返回一个新的limit的缓冲区对象
- Buffer mark():设置Buffer的mark位置,它只能在0和position之间做mark
- int position:返回position的值
- int position(int newPs):设置Buffer的position,并返回position被修改后的Buffer对象
- Buffer reset():将位置(position)转到mark所在位置
- Buffer rewind():将位置(position )设置成0,取消设置的mark
- put():放入数据
- get():取出数据
使用Channel
Channel类似于传统的流对象,但与传统的流对象有两个主要区别
- Channel可以直接将指定文件的部分或全部直接映射成Buffer
- 程序不能直接访问Channel中的数据,包括读取,写入都不行,Channel只能与Buffer交互。如果要从Channel中取得数据,必须先用Buffer从Channel中取出一些数据,然后让程序从Buffer中取出这些数据;如果要将程序中的数据写入Channel,先把数据放入Buffer中,程序再将Buffer里的数据写入Channel中。
Channel的实现类:
- DatagramChannel:支持UDP网络通信的Channel
- FileChannel:支持文件读写的Channel
- Pipe.SinkChannel:支持线程之间通信的Channel
- Pipe.SourceChannel:支持线程之间通信的Channel
- SelectableChannel:支持线程之间通信的Channel
- ServerSocketChannel :Socket通信的服务端
- SocketChannel:Socket通信的客户端