概述:
NIO核心:Channel、Buffer、Selector(非阻塞式输入/输出)。传统的IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer进行操作,数据从通道读到缓冲区或者从缓冲区写到通道中;传统IO和NIO都是用于进行输入/输出的功能,但NIO采用了内存映射文件的方式来处理输入/输出,NIO将文件或文件的一端区域映射到内存中,这样就可以像访问内存一样来访问文件;
Channel是对传统输入/输出系统中的模拟,在NIO系统中所有数据都需要通过通道传输;Channel与InputStream、OutputStream最大的区别在于它提供了一个map方法,通过map方法可以直接将“一块数据”映射到内存中。如果传统的输入/输出是面向流的,则NIO是面向块的;
Buffer则是一个容器,本质是一个数组,发送到Channel中的所有对象都需先放到Buffer中,而从Channel中取到的数据也需先读到Buffer中;
Buffer:
Buffer是一个抽象类,其子类:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer;
Buffer的三个概念:
- 容量:是它所包含的元素的数量。缓冲区的容量不能为负并且不能更改;
- 界限:第一个不应该读取或写入的元素的索引。缓冲区的限制不能为负,并且不能大于其容量,即位于其后的数据不可读也不可写;
- 位置:下一个要读取或写入的元素的索引。缓冲区的位置不能为负,并且不能大于其限制。对于每个非 boolean 基本类型,此类都有一个子类与之对应。
Buffer还有一个可选的标记(mark),该mark允许程序直接将position定位到mark处;
Buffer类定义了对缓冲区进行的操作:
- clear():使缓冲区为一系列新的通道读取或相对放置 操作做好准备:它将限制设置为容量大小,将位置设置为 0(执行以后,该Buffer对象里的数据依然存在)。
- flip():使缓冲区为一系列新的通道写入或相对获取 操作做好准备:它将限制设置为当前位置,然后将位置设置为 0。
- rewind():使缓冲区为重新读取已包含的数据做好准备:它使限制保持不变,将位置设置为 0;
方法摘要 | |
---|---|
abstract Object | array() 返回此缓冲区的底层实现数组(可选操作)。 |
abstract int | arrayOffset() 返回此缓冲区的底层实现数组中第一个缓冲区元素的偏移量(可选操作)。 |
int | capacity() 返回此缓冲区的容量。 |
Buffer | clear() 清除此缓冲区。 |
Buffer | flip() 反转此缓冲区。 |
abstract boolean | hasArray() 告知此缓冲区是否具有可访问的底层实现数组。 |
boolean | hasRemaining() 告知在当前位置和限制之间是否有元素。 |
abstract boolean | isDirect() 告知此缓冲区是否为直接缓冲区。 |
abstract boolean | isReadOnly() 告知此缓冲区是否为只读缓冲区。 |
int | limit() 返回此缓冲区的限制。 |
Buffer | limit(int newLimit) 设置此缓冲区的限制。 |
Buffer | mark() 在此缓冲区的位置设置标记。 |
int | position() 返回此缓冲区的位置。 |
Buffer | position(int newPosition) 设置此缓冲区的位置。 |
int | remaining() 返回当前位置与限制之间的元素数。 |
Buffer | reset() 将此缓冲区的位置重置为以前标记的位置。 |
Buffer | rewind() 重绕此缓冲区。 |
public static void main(String[] args) {
CharBuffer charBuffer=CharBuffer.allocate(8);
System.out.println(charBuffer.capacity());
System.out.println(charBuffer.limit());
System.out.println(charBuffer.position());
charBuffer.put('A');
charBuffer.put('B');
charBuffer.put('C');
System.out.println(charBuffer.position());
charBuffer.flip();
System.out.println(charBuffer.limit());
charBuffer.clear();
System.out.println(charBuffer.capacity());
System.out.println(charBuffer.limit());
System.out.println(charBuffer.position());
System.out.println(charBuffer.get(2));
}
Channel:
Channel类似于传统的流对象,但有两个区别:
- Channel可以直接将指定文件的部分或全部直接映射成Buffer;
- 程序不能直接访问Channel中的数据,包括读写,Channel只能与Buffer进行交互;
public static void main(String[] args) {
Path path=null;
FileChannel fileChannel=null;
try{
path= Paths.get("C:\\Users\\Administrator\\IdeaProjects\\FUXI\\src\\nio\\TestBuffer.java");
fileChannel=FileChannel.open(path, StandardOpenOption.READ);
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
int readLine=-1;
while ((readLine=fileChannel.read(byteBuffer))>0){
byteBuffer.flip();
Charset charset=Charset.forName("UTF-8");
System.out.println(charset.decode(byteBuffer));
byteBuffer.clear();
}
}catch (IOException e){
e.printStackTrace();
}finally {
try {
fileChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}