Java NIO

概述:

  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处;

0\leqslant mark \leqslant position \leqslant limit \leqslant capacity

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();
            }
        }
    }

 

 

你可能感兴趣的:(Java基础)