NIO系列2:Buffer的理解

本文参考至:http://ifeve.com/buffers/

Buffer的本质理解:

Java NIO中的Buffer用于和NIO通道进行交互。数据是从通道读入缓冲区,从缓冲区写入到通道中的。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * Buffer的理解 还是使用FileChannel的代码案例
* 首先介绍Buffer的基本用法:
*
* 1、创建Buffer实例(创建的时候可以初始化Buffer对象的容量通过ByteBuffer.allocate(int capacity))
*
* 2、将Channel的数据写入到Buffer对象中(例如:channel.read(buffer))
*
* 3、Buffer对象调用flip()方法(flip()方法的作用是:将buffer从写模式切换到读模式
*
* 4、Buffer对象调用clear()方法清空buffer缓冲区中的所有数据(其实可以使用compact()方法:compact() * 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面。) * * @author 李嘉明 * @2017-3-21 */ public class BufferMean { public static void main(String[] args) throws IOException { File file = new File("F:/jia.txt"); FileInputStream fileInput = new FileInputStream(file); FileChannel fileChannel = fileInput.getChannel(); // 1、创建Buffer实例并初始化Buffer对象的容量(48byte) ByteBuffer byteBuffer = ByteBuffer.allocate(48); // 2、将Channel的数据写入到Buffer对象 int bytesRead = fileChannel.read(byteBuffer); while (bytesRead != -1) { // 3、从写模式切换到读模式 byteBuffer.flip(); while (byteBuffer.hasRemaining()) { System.out.print((char) byteBuffer.get()); } System.out.println(" ----read " + bytesRead); // 4、清空Buffer对象缓冲区的所有数据 byteBuffer.clear(); // 再次将通道的数据写入到buffer中,这里返回的值是本次从通道读取的数据的字节数 bytesRead = fileChannel.read(byteBuffer); } } }

如果想要清晰了解Buffer的allocate()、filp()方法和工作原理,那么就必须要理解Buffer中的几个重要的成员变量:
1、capacity(Buffer的总容量)
2、position
3、limit

position:

写数据到Buffer中时,position表示当前的位置。初始的position值为0。当一个单元的数据写到Buffer后, position会向前移动到下一个可插入数据的Buffer单元。position最大可为capacity – 1。当读取数据时,也是从某个特定位置读。当将Buffer从写模式切换到读模式,position会被重置为0. 当从Buffer的position处读取数据时,position向前移动到下一个可读的位置。

limit:

在写模式下,Buffer的limit表示你最多能往Buffer里写多少数据。 写模式下,limit等于Buffer的capacity。当切换Buffer到读模式时, limit表示你最多能读到多少数据。因此,当切换Buffer到读模式时,limit会被设置成写模式下的position值。换句话说,你能读到之前写入的所有数据(limit被设置成已写数据的数量,这个值在写模式下就是position)

这一设计相当巧妙

下面是filp()和clear()的源码:

 public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }

跟一般的清空数据不一样,buffer的clear()方法被调用之后并不会把数据清空,而是把写入的位置置为0,然后在写入的时候对之前的缓存。

    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }

上面这样设计的好处可以在Buffer的rewind()方法里面体现:Buffer.rewind()将position设回0,limit保持不变。所以你可以重读Buffer中的所有数据。

如果从想从Buffer读取数据到Channel可以尝试:

int bytesWritten = inChannel.write(buf);

你可能感兴趣的:(NIO系列2:Buffer的理解)