Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java NIO Buffer #16

Open
DraperHXY opened this issue Jan 17, 2019 · 0 comments
Open

Java NIO Buffer #16

DraperHXY opened this issue Jan 17, 2019 · 0 comments
Assignees

Comments

@DraperHXY
Copy link
Owner

Buffer 的基本用法

使用 Buffer 一般遵循以下四个步骤

  1. 写入数据到 Buffer
  2. 调用 flip() 方法
  3. 从 Buffer 中读取数据
  4. 调用 clear() 方法或者 compact() 方法

当向 buffer 写入数据时, buffer 会记录下写了多少数据。一旦要读取数据,需要通过 flip() 方法将 Buffer 从写模式切换到读模式(即将 position 从最后一个切换到第一个, 翻转 buffer)。
一旦读完了所有的数据,就需要清空缓冲区,让它可以再次被写入。
有两种方式能够清空缓冲区:

  • clear() 清空整个缓冲区
  • compact() 清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面

Buffer 的 capacity,position 和 limit

缓冲区本质是一块可以写入数据,然后从中读取数据的内存。这块内存被包装成 NIO Buffer 对象,并提供了一组方法,用来访问该内存。

其中有三个主要的属性

  • capacity
  • position
  • limit

position 和 limit 的含义取决于 Buffer 处在读模式还是写模式。不管 Buffer 处在什么模式,capacity 的含义总是一样的。
下面有一个图可以让理解一目了然

capacity

作为一个内存块,Buffer 有一个固定大小值 capacity,你只能往里写 capacity 个 byte,long,char 等类型。一旦 Buffer 满了,组需要清空 (通过读数据,然后调用 compact() 方法,或者 clear 数据才能继续写数据)

position

当你写数据到 Buffer 中时, position 表示当前的位置。出事的 position 值为 0。当一个 bvte,long 等类型的数据写到 Buffer 后, position 会向前移动到下一个可插入数据的 Buffer 单元,position 最大可为 capaciry - 1
当读取数据时,也是从某个特定的位置读。当将 Buffer 从写模式切换到读模式,position 会被重置为 0,limit 设置为之前的 position

Buffer 的类型

  • ByteBuffer
  • MappedByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer

这些 Buffer 代表了不同的数据类型。换句话说可以通过这些类型来操作缓冲区中的字节
其中 MappedByteBuffer 有些特别

Buffer 的分配

要获取一个 Buffer 对象,首先要进行分配。每一个 Buffer 类都有一个 allocate 方法。

// Reads a sequence of bytes from this channel into the given buffer,
// starting at the given file position.
ByteBuffer buffer = ByteBuffer.allocate(48);

向 Buffer 中写数据

一般有两种方式写数据到 Buffer 中

  • 从 Channel 写到 Buffer
int bytesRead = channel.read(buffer);
  • 通过 Buffer 的 put() 方法写到 Buffer 里
buf.put(127);

put 有很多版本,例如写到一个指定的位置,或者把一个字节数组写入到 Buffer。

flip() 方法

flip() 方法将 Buffer 从写模式切换到读模式。调用 flip() 方法会将 position 设为 0,并将 limit 设置成之前 position 的值,所以 flip 也叫翻转。

从 Buffer 中读取数据

一般有两种方式可以从 Buffer 中读取数据

  • 从 Buffer 读取数据到 Channel
// Writes a sequence of bytes to this channel from the given buffer.
int byte = channel.write(buffer);
  • 使用 get(0 方法从 Buffer 中读取数据
byte byte = buf.get();

rewind() 方法

使 position 设回 0,所以可以重读 Buffer 中的所有数据。limit 保持不变,仍然表示能从 Buffer 中读取多少个元素

clear() 和 compact() 方法

上面有过描述了,再不赘述

mark() 和 reset() 方法

通过 mark() 方法来标记这个特殊的 position,然后调用 reset() 方法恢复到这个特殊的 position

equals() 和 compareTo() 方法

equals()

当满足下列条件时,表示两个 Buffer 相等

  • 有相同的类型
  • Buffer 中剩余的 byte,char 等个数相等
  • Buffer 中所有剩余的 byte, char 等都相同(只在这里比较了每一个 byte)

compareTo()

比较两个 Buffer 的剩余元素,如果满足下列条件,则认为一个 Buffer 小于另一个 Buffer

  • 第一个不相等的元素小于另一个 Buffer 中对应的元素
  • 所有元素都相等,但第一个 Buffer 比另一个先耗尽(第一个 Buffer 的元素比另一个少)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant