Java NIO流

来源:互联网 发布:少林足球影评知乎 编辑:程序博客网 时间:2024/05/19 14:37

       对于JavaNIO还是不是很了解,之前认为NIO的N是non-block IO的意思,非阻塞;但是原来是New IO的意思。这个新表示的是和原来的BIO而言是一种新的IO吧。NIO的主要特性就是缓冲区,通道,和选择器(这个可能不是)。

      Java在JDK1.4版本呢,引入了NIO这个新的api。Sun公司官方说明NIO的特性如下:

1. 为所有的原始类型提供了(Buffer)缓存支持;

2. 字符集编码解码解决方案

3. Channel(通道):一个新的原始I/O抽象;

4. 支持锁和内存映射文件的文件访问接口;

5. 提供多路(non-blocking)非阻塞式的高伸缩网络I/O

      对于上面的特性,我是不大了解的。不过,不影响,我们继续介绍。

      NIO创建的目的是,实现高速的I/O,而无需编写自定义的本机代码。

      那NIO大概是怎么做到的呢?它将最耗时的I/O操作转回操作系统,因而可以极大的提高速度。而最耗时的I/O操作是填充和提取缓冲区。

      原来的io和现在NIO最重要的区别就是,数据打包和传输的方式。以前是以流,现在是以块的方式处理数据。

      之前用流的方式呢,只能一次一个字节的处理数据。一个输入流产生一个字节的数据,而一个输出流则消耗一个字节的数据。这样的好处是,创建过滤器特别容易,可以创建多个过滤器,每个过滤器处理只处理一部分的数据。坏处就是,比较慢。

      而NIO用块的方式呢,可以一次一个块的处理数据。每一步的操作都在产生或者消耗一个块,好处是相对于流快得多,坏处是,不够优雅和简单。

缓冲区

      然后开始介绍缓冲区,缓冲区就是上面介绍到的NIO的特性第一条,为所有的原始数据都提供了Buffer缓存的支持。它主要是将所有的原始数据放在数组中,以块的形式处理。

      而每种缓冲区的类都有四个属性:容量(Capacity),上界(Limit),位置(Position),以及标记(Mark),用于提供关于其所包含的数据元素的信息。

      容量:缓冲区能够容纳的数据元素的最大数量,缓冲区创建时确定,永远不能被改变;

      上界:缓冲区第一个不能被读或写的元素,或者说,缓冲区现存元素的计数。

      位置:下一个要被读或写的元素的索引。该值会自动由相应的get(),put()函数更新;

      标记:一个备忘的位置。调用mark()来设定mark=position。调用reset()来设定position = mark;标记在设定前是未定义的undefined。

      缓冲区的分类有,ByteBuffer(字节缓冲区),CharBuffer(字符缓冲区),ShortBuffer(短整型缓冲区),IntBuffer(整型缓冲区),LongBuffer(长整型缓冲区),FloatBuffer(单精度浮点缓冲区),DoubleBuffer(双精度浮点缓冲区),就是没有布尔缓冲区。

      他们都是抽象类,所以不能实例化,然后他们都继承了Buffer类,所以都有存get(),取set()方法,也都可以通过各自的静态方法allocation,创建缓冲区。该方法是通过warpping将现有的数组包装到缓冲区中来为缓冲区的内容分配空间,或者通过创建现有字节缓冲区的视图来创建。

      下面这是一个简单的实例,从上到下,创建一个整型的缓冲区,然后将现有的数组放到该缓冲区中。可以通过put改变数组中的数据,并且由于缓冲区中的数据对数组是可见的,所以改变缓冲区也会改变数据,可以认为是传引用。flip(),由于get()每调用一次,position位置都会改变,本来pos会等于3的,而用flip可以让pos变为0;clear()效果也一样。而duplicate()可以复制一个缓冲区,一模一样,也是传引用,修改哪个都会影响到另一个。

import java.nio.IntBuffer;import java.util.Arrays;/** * Created by liuyanling on 2017/6/30. */public class BufferTest {    public static void main(String[] args) {        //创建缓冲区,并指定大小        IntBuffer  intBuffer = IntBuffer.allocate(10);        //给缓冲区赋值,建立数组        int[] intArray = new int[]{3,5,7};        intBuffer = intBuffer.wrap(intArray);        //修改元素        intBuffer.put(0,9);        //打印缓冲区数据        for(int i=0;i<intBuffer.limit();i++) {           System.out.print(intBuffer.get()+"\t");           //System.out.print(intBuffer+"\t"); //        }        System.out.println("\n缓冲区的数据对数组是可见的,修改视图,数组中的数据也会变;传引用");        //打印原始数组        Arrays.stream(intArray).forEach(temp-> System.out.print(temp+"\t"));        //intBuffer.flip();//get()会使pos改变,对缓冲区进行反转,将limit=pos;pos=0; (将当前位置给limit,然后变为0)        intBuffer.clear();        System.out.println(intBuffer);        IntBuffer intBuffer2 = intBuffer.duplicate();        System.out.println(intBuffer2);        intBuffer2.put(0,11);        //0 <= mark <= position <= limit <= capacity        //打印缓冲区数据        for(int i=0;i<intBuffer.limit();i++) {            System.out.print(intBuffer.get()+"\t");        }        System.out.println("\n复制的缓冲区对原来的缓冲区也是可见的;传引用");        //打印原始数组        for(int i=0;i<intBuffer2.limit();i++) {            System.out.print(intBuffer2.get()+"\t");        }    }}
      结果是这样

957缓冲区的数据对数组是可见的,修改视图,数组中的数据也会变;传引用957java.nio.HeapIntBuffer[pos=0 lim=3 cap=3]java.nio.HeapIntBuffer[pos=0 lim=3 cap=3]1157复制的缓冲区对原来的缓冲区也是可见的;传引用1157
      未完待续!



     


原创粉丝点击