美文网首页
2.NIO通道与缓冲区

2.NIO通道与缓冲区

作者: xialedoucaicai | 来源:发表于2018-05-13 22:36 被阅读0次

通道就是IO源与目标之间的连接,类似IO中的流,不过通道本身并不能直接访问数据,就像铁路一样,负责传输。
缓冲区就是装载源或目标的容器,类似IO中的byte[],直接操作数据(将文件读入缓冲区,将缓冲区中的数据写入文件),就像火车一样,负责装货。
一句话:通道用于传输,缓冲区用于存取。

除了Boolean类型,其他基本类型都有对应的缓冲区,我们常用的是ByteBuffer。Buffer的重要属性:

private int mark = -1;//标记position的位置,结合reset让position回到当时mark的位置

private int position = 0;// 当前操作数据的位置

private int limit; //可操作数据量

private int capacity;// 缓冲区最大容量

四者的关系:
mark <= position <= limit <= capacity
来张图可能更好理解:


buffer的属性

话不多说,直接上例子:

public void testBuffer(){
    String s = "abced";
    //allocate分配指定大小的缓冲区
    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
    System.out.println("-------allocate()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    
    //put向缓冲区加入内容
    byteBuffer.put(s.getBytes());
    System.out.println("-------put()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    
    //flip切换成读模式
    byteBuffer.flip();
    System.out.println("-------flip()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    
    //get读取缓冲区
    byte [] dest = new byte [byteBuffer.limit()];
    byteBuffer.get(dest);
    System.out.println("读取到的数据"+new String(dest));
    
    System.out.println("-------get()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    
    //rewind恢复到上次读取初始状态,可以重复读取数据
    byteBuffer.rewind();
    System.out.println("-------rewind()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    
    //clear清空缓冲区,但缓冲区中的数据仍然存在,只是处于被遗忘状态
    byteBuffer.clear();
    System.out.println("-------clear()-----------");
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
    //这里仍然能够读取到
    System.out.println((char)byteBuffer.get());
    System.out.println("position->"+byteBuffer.position());
    System.out.println("limit->"+byteBuffer.limit());
    System.out.println("capacity->"+byteBuffer.capacity());
}

mark()和reset()结合使用:

public void testMark(){
    String s = "abced";
    
    //allocate分配指定大小的缓冲区
    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
    //放入数据
    byteBuffer.put(s.getBytes());
    //切换到读
    byteBuffer.flip();
    //读2个字节
    byte dest [] = new byte [2];
    byteBuffer.get(dest,0,2);
    System.out.println(byteBuffer.position());//2
    //进行标记
    byteBuffer.mark();
    //再读2个字节
    byteBuffer.get(dest,0,2);
    System.out.println(byteBuffer.position());//4
    //让position回到上次标记的位置
    byteBuffer.reset();
    System.out.println(byteBuffer.position());//2
    
    //判断缓冲区是否仍有可操作数据
    if(byteBuffer.hasRemaining()){
        //还有多少可操作数据
        System.out.println(byteBuffer.remaining());//3
    }
}

flip()和clear(),应该是操作buffer时候用的最多的。经过测试和分析API(其实看源码可以发现这些方法其实就是在改变buffer的四个属性值),发现如下最佳实践:

  1. buffer写入之后,读取时,需要先执行flip()。注意这里的读取是指读取buffer,读取和写入是相对的,对文件是写入,对buffer就是读取
  2. 复用buffer,再次写入之前,最好先执行clear()方法
    上代码:
public void testFlip(){
    ByteBuffer byteBuffer = ByteBuffer.allocate(10);
    byteBuffer.put("12345".getBytes());
    //写模式切换成读模式
    byteBuffer.flip();
    String s = new String(byteBuffer.array(),0,byteBuffer.limit());
    System.out.println(s);
    
    //复用buffer之前,最好先清空
    byteBuffer.clear();
    byteBuffer.put("6".getBytes());
    byteBuffer.flip();
    System.out.println(new String(byteBuffer.array(),0,byteBuffer.limit()));
}

相关文章

  • 2.NIO通道与缓冲区

    通道就是IO源与目标之间的连接,类似IO中的流,不过通道本身并不能直接访问数据,就像铁路一样,负责传输。缓冲区就是...

  • Nio的研究

    1.Nio是面向缓冲区,传统流是面向流的 2.Nio是非阻塞式的,流是阻塞式的 3.Nio两个重要概念 (1)通道...

  • Java NIO之Buffer

    Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。缓冲区本...

  • Java NIO中的Buffer

    Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。缓冲区本...

  • Netty源码之写入数据

    写入数据,是从缓冲区写入到通道中。读取数据和写入数据是相对概念,从通道读取到缓冲区,从缓冲区写入到通道。Pipel...

  • Java NIO系列教程(三) Buffer

    Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的...

  • JAVA-NIO之Buffer

    Java NIO中的Buffer用于和NIO通道进行交互。如你所知,数据是从通道读入缓冲区,从缓冲区写入到通道中的...

  • NIO框架组件详解!详细解析Buffer的基本使用和常用方法

    Buffer的概念 Java NIO中的Buffer用于和NIO通道进行交互数据是从通道读入缓冲区数据是从缓冲区写...

  • IO 和 NIO的区别,NIO优点

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标...

  • 面试题:关于一些nio的问题资料

    Java NIO提供了与标准IO不同的IO工作方式: Channels and Buffers(通道和缓冲区):标...

网友评论

      本文标题:2.NIO通道与缓冲区

      本文链接:https://www.haomeiwen.com/subject/mqxqdftx.html