Buffer是一块将要写到Channel里的数据,或者刚从Channel里读出来的数据。它是用来保存数据的一个对象,并且作为NIO Channel的其中一个端点(另一端可能是网络或者文件等)。Buffer提供了一种访问数据的机制,并且跟踪数据读写流程。

Buffer是Java 老的IO和NIO的主要不同之一。以前老的IO直接从流中读或者写。现在数据是从Buffer中都数据或者将写的数据写入Buffer中。在NIO中,Channel就相当于以前的Stream。了解更多NIO Channel可以访问这里

Buffer特点:

1 Buffer是NIO的基本构建块。 2 提供固定大小的容器来读写数据。 3 每一个Buffer都是可读的,但是选中的Buffer才可以写。 4 Buffer是Channel的其中一个端点。 5 在只读Buffer中数据内容是不可变的,但是Buffer的mark,position,limit是可以变的。 6 默认Buffer不是线程安全的。

Buffer类型:

每一个原生类型都有对应的Buffer类型。所有的Buffer类型都实现了Buffer接口。最常用的Buffer类型是ByteBuffer。在Java NIO包中包含如下的Buffer类型:ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloatBuffer,DoubleBuffer,MappedByteBuffer。

Buffer Capacity:

Buffer是固定大小的类型。如果Buffer满了,那么必须先clear,然后才能继续写入。一旦Capacity被设置就不能再改。

Buffer Limit:

在写模式中,Buffer的limit和capacity相同。在读模式中,limit是最后写入数据的索引加1。随着Buffer不断写入,Limit会保持增长。0 <= limit >= capacity

Buffer Position:

position指向Buffer的当前位置。当Buffer刚被新建的时候,position指向0,当读或者写的时候,position增加到下一个索引。Position在0和Limit之间。

Buffer Mark:

Mark就像对Buffer中的位置做了一个书签。当调用mark()方法的时候,当前的position会被记录。调用reset()方法可以恢复到之前mark的position。

Buffer flip,clear,rewind:

flip():调用此方法,使得Buffer准备开始读或者开始一系列新的写。设置limit=position,position=0. clear():调用此方法,使得Buffer准备开始写或者启动一系列的新的读。设置limit=capacity,position=0. rewind():想要从头开始读时,调用此方法,会把position设成0.

从Buffer中读数据示例代码:

ByteBuffer byteBuffer = ByteBuffer.allocate(512);
byteBuffer.flip(); //Flip the buffer to prepare for read operation.
int numberOfBytes = fileChannel.read(byteBuffer);
char c = (char)byteBuffer.get();

向Buffer中写数据:

ByteBuffer byteBuffer = ByteBuffer.allocate(512);
byteBuffer.put((byte) 0xff);

在NIO中,如果你要向文件中写数据,先把数据写入到Buffer,然后用Channel把Buffer写入到文件。与此同理,如果要从文件读数据,用Channel把数据从文件读到Buffer,然后从Buffer中取数据。

package com.javapapers.java.nio;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

public class BufferExample {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("temp.txt");
        write(path);
        read(path);
    }

    private static void write(Path path) throws IOException {
        String input = "NIO Buffer Hello World!";
        byte[] inputBytes = input.getBytes();
        ByteBuffer byteBuffer = ByteBuffer.wrap(inputBytes);
        FileChannel channelWrite = FileChannel.open(path,
                StandardOpenOption.CREATE, StandardOpenOption.WRITE);
        channelWrite.write(byteBuffer);
        channelWrite.close();
    }

    private static void read(Path path) throws IOException {
        FileChannel channelRead = FileChannel.open(path);
        ByteBuffer byteBuffer = ByteBuffer.allocate(512);
        channelRead.read(byteBuffer);
        byte[] byteArray = byteBuffer.array();
        String fileContent = new String(byteArray).trim();
        System.out.println("File Content: " + fileContent);
        channelRead.close();
    }
}

本文翻译自 http://javapapers.com/java/java-nio-buffer/,仅供参考和学习。