NIO

NIO概述

为什么了有了IO,还需要有NIO?

* NIO在JDK1.4后引入的

* NIO是面向块(缓冲区)编程,旧IO是面向流编程

*

* IO     NIO

* 面向流          面向缓冲区

* 阻塞IO 非阻塞IO

* 无           选择器

*

* Java中针对IO的一些核心的包和接口、类

*

* java.nio 主要包含了各种与Buffer相关的类

* java.nio.channel 主要包含了与Channel和Selector相关的类和接口

* java.nio.charset 主要包含了与编码相关的类接口

* java.nio.channels.spi 主要包含了与Channel相关的服务提供者编程接口

* javan.nio.charset.spi 主要包含了与charset相关的服务提供者编程接口

*

*

* 目前需要掌握的核心就是三个包

* Buffer

* Channel

* CharSet

*

* 面向缓冲区编程:

*         数据的读写必须经过缓冲区

*  我们可以使用Buffer所对应的子类来数据从通道(Channel)流向缓冲区

*  从缓冲区写到通道叫做读取缓冲区

Buffer缓冲区

Buffer

* Buffer是一个抽象类

* 子类有

*         ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer

*

* 核心类

*         ByteBuffer和CharBuffer

* ByteBuffer有一个子类 MappedByteBuffer

* MappedByteBuffer类能够将文件直接映射到内存中,那么这样我们就可以像访问内存一样访问文件,非常方便

*

* 获取Buffer

*         获取ByteBuffer

*                 static ByteBuffer allocate(int capacity)

                         分配一个新的字节缓冲区。

               static ByteBuffer allocateDirect(int capacity)

                         分配新的直接字节缓冲区。

        二者获取Buffer的区别

        1.创建普通Buffer成本低,读写的效率不高

        2.因为创建直接Buffer成本高,所以我们一般用在Buffer生存周期较长的时候使用

        3.只有ByteBuffer才能够创建直接Buffer,其他的Buffer对象是不能够创建

        4.如果创建了直接Buffer但是我又想要使用其他Buffer的功能,可以将ByteBuffer转换成其他Buffer

                        asIntBuffer()

* 四个非常重要的概念

*         capacity: 缓冲区的容量,不可以为负数,一旦创建了就不能够改变

*  limit: 无效缓冲区的第一个位置索引,limit后面的数据既不可读,也不可写

*  position : 下一个可以被读取或者写入的缓冲区位置索引

*  mark: 标记索引,该索引能够用于下次读取或者写入,它只能够在0-position之间

*  

*  四个系数的关系:

*          0 < mark < postion < limit < capacity

*  

*  五个方法

*          flip(): 将写模式切换为读模式, 将limit的值改为postion的值,同时将postion归0

*                          特点: 就是为下一次数据的读取做好准备

*          clear(): 将读模式切换为写模式,将limit改为capacity的值,同时将postion归0

*                          特点: 就是为下一次数据的写入做好准备

*          put(): 相对读取,向Buffer中存储数据

*          get(): 相对读取,从Buffer中获取数据

*          hasRemaining(): 判断当前位置和limit之间是否还有元素可处理

*

* 绝对读取: get(index) 不会影响position的位置

* 相对读取: put() get() 会影响,每次读取一次,指针后移

*/

public class NIODemo02 {

       public static void main(String[] args) {

//                ByteBuffer buffer = ByteBuffer.allocate(5);

//                ByteBuffer buffer2 = ByteBuffer.allocateDirect(10);

               CharBuffer buffer = CharBuffer.allocate(8);

               // Buffer已经准备好了向Buffer中写数据    写模式

               System.out.println("capacity:" + buffer.capacity()); // 8

               System.out.println("limit:" + buffer.limit()); // 8

               System.out.println("position:" + buffer.position()); // 0


               buffer.put('a');

               buffer.put('b');

               buffer.put('c');

               System.out.println("------------------------");


               System.out.println("capacity:" + buffer.capacity()); // 8

               System.out.println("limit:" + buffer.limit()); // 8

               System.out.println("position:" + buffer.position()); // 3


               System.out.println("------------------------");

               // 切换模式  ,limit变为position的位置然后将position变为0

               buffer.flip();

               System.out.println("capacity:" + buffer.capacity()); // 8

               System.out.println("limit:" + buffer.limit()); // 3

               System.out.println("position:" + buffer.position()); // 0


               System.out.println("------------------------");

//                char ch = 0;

//                ch = buffer.get();

//                System.out.println(ch);

//                ch = buffer.get();

//                System.out.println(ch);

//                

////                System.out.println("capacity:" + buffer.capacity()); // 8

////                System.out.println("limit:" + buffer.limit()); // 3

////                System.out.println("position:" + buffer.position()); // 2

//                ch = buffer.get();

//                System.out.println(ch);

//                

//                ch = buffer.get();

//                System.out.println(ch);


               int ch = 0;

               while (buffer.hasRemaining()) {

                       ch = buffer.get();

                       System.out.println((char)ch);

               }


               System.out.println("------------------");

               buffer.clear(); // 将postion 清 0 ,将limit = capacity


               System.out.println("capacity:" + buffer.capacity()); // 8

               System.out.println("limit:" + buffer.limit()); // 8

               System.out.println("position:" + buffer.position()); // 0


               // 注意: 调用clear方法只是将读模式改为写模式,并不会清空缓冲区的数据

               System.out.println(buffer.get(1));

               System.out.println("执行绝对读取之后Buffer的position位置:" + buffer.position());

       }

}

Channel通道

* Channel原理类似于传统的流对象, FileInputStream FileOutputStream

* 但是有两个主要的区别

*         1.Channel能够将指定的部分或者全部文件映射到内存中

*                 全部映射

*                         MappedByteBuffer

*                 部分文件映射

*  2.程序如果想要读取Channel中的数据,不能够直接读写,必须经过Buffer

*  

*  Java中为Channel提供了如下常用的类

*  

*  FileChannel 和文件相关的通道

*  DatagramChannel 和UDP协议传输数据相关的通道

*  SocketChannel 和TCP协议相关的数据传输通道

*  ServerSocket 和TCP协议相关的数据传输通道

*  

*  获取FileChannel对象

*  和文件相关的普通流有哪些?

*          FileInputStream FileOutputStream RandomAccessFile

*  常用的方法

*  read() : 将Channel中的数据读取到Buffer中

*  write() : 向Buffer中写入数据

*  map(): 将channel中的数据全部或者部分映射到Buffer中

*                  inChannel.map(mode, position, size)

*                  MappedByteBuffer mappBuffer = inChannel.map(MapMode.READ_ONLY, 0, srcFile.length());

*/

CharSet字符集

Charset 理解为现实生活的编码表对象

*/

public class NIODemo05 {

       public static void main(String[] args) throws CharacterCodingException {

               // 获取当前JDK所支持的所有编码类型

//                SortedMap map = Charset.availableCharsets();

//                

//                for (String key : map.keySet()) {

//                        Charset charset = map.get(key);

//                        System.out.println(charset);

//                }


               // 知道了对应JDK认可的字符集别名后,那么我们就可以来获取对应的字符集对象

               Charset charset = Charset.forName("GBK");


               // 创建编码器  编码 字符/字符串/字符数组 --> 字节

               CharsetEncoder encoder = charset.newEncoder();

               // 创建解码器  解码 上述相反

               CharsetDecoder decoder = charset.newDecoder();


               CharBuffer charBuffer = CharBuffer.allocate(10);

               charBuffer.put("abc");

               charBuffer.flip();


               ByteBuffer byteBuffer = encoder.encode(charBuffer);


               for (int i = 0; i < byteBuffer.limit(); i++) {

                       System.out.println(byteBuffer.get(i));

               }


               System.out.println(decoder.decode(byteBuffer));

       }

}

你可能感兴趣的:(NIO)