如何从 ByteBuffer 中提取使用过的字节数组?

Posted

技术标签:

【中文标题】如何从 ByteBuffer 中提取使用过的字节数组?【英文标题】:How to extract used byte array from ByteBuffer? 【发布时间】:2018-03-14 23:08:57 【问题描述】:

java.nio.ByteBuffer 类有一个ByteBuffer.array() 方法,但是这会返回一个数组,该数组是缓冲区容量的大小,而不是已用容量。因此,我遇到了一些问题。

我有一个字节缓冲区,我将其分配为某种大小,然后我将数据插入到它。

ByteBuffer oldBuffer = ByteBuffer.allocate(SIZE);
addHeader(oldBuffer, pendingItems);
newBuffer.flip();
oldBuffer.put(newBuffer);
// as of now I am sending everything from oldBuffer
send(address, oldBuffer.array());

我怎样才能发送oldBuffer 中正在使用的内容。有没有一种班轮可以做到这一点?

【问题讨论】:

修改send() 方法以接受长度(和偏移量)或将实际ByteBuffer 作为参数会更简单。你不应该像这样复制数据。 【参考方案1】:

您可以翻转缓冲区,然后使用缓冲区的剩余大小创建一个新数组并填充它。

oldBuffer.flip();
byte[] remaining = new byte[oldBuffer.remaining()];
oldBuffer.get(remaining);

flip() 和 Arrays.copyOf 的另一种方式

oldBuffer.flip();
Arrays.copyOf(oldBuffer.array(), oldBuffer.remaining());

没有flip()

Arrays.copyOf(oldBuffer.array(), oldBuffer.position());

也像 EJP 说的,如果你可以访问send(..) 方法,你可以在send() 方法中添加一个大小和偏移量参数,而无需创建和填充一个新数组。

【讨论】:

是的,我确实可以使用send 方法,那么我们可以对其进行哪些更改?你能举个例子来说明一下吗? 这取决于您如何处理send 方法中的数据,如果您最终需要该长度的数组,您可以这样做,只需调用send(..) 方法和无需修改任何东西。此外,如果数据不多,您可以复制数组。 是的,我确实需要那个长度的发送方法中的字节数组。 with flip() versionwithout flip() version 之间还有什么区别? 好吧,如果迟早你需要那个长度的数组,那么你可以早点做。 Flip() 更改ByteBuffer 的限制、位置和标记值,通常在读取前使用。数组是一样的,所以实际上差别不大,如果你不再使用那个缓冲区,根本没有差别。【参考方案2】:

缓冲区的position()表示缓冲区中使用的数据量。

所以创建一个该大小的字节数组。

接下来转到缓冲区的位置 0,因为您必须从那里读取数据。 rewind() 这样做。

然后使用get()方法将缓冲区数据复制到数组中。

byte[] data = new byte[buffer.position()];
buffer.rewind();
buffer.get(data);

另请注意,buffer.array() 仅在 buffer.hasArray() 返回 true 时有效。所以在调用它之前检查hasArray()。否则,buffer.array() 将抛出以下任何异常。

    UnsupportedOperationException - 在直接缓冲区上调用它时。 ReadOnlyBufferException - 如果缓冲区是只读的。

【讨论】:

以上是关于如何从 ByteBuffer 中提取使用过的字节数组?的主要内容,如果未能解决你的问题,请参考以下文章

从字节缓冲区中提取值

如何从 ByteBuffer 中获取已使用的 byte[]

如何从 ByteBuffer 转换为 Integer 和 String?

如何将一个字节数组转换为两个长值?

Java - 从套接字通道读取

如何正确使用 ByteBuffer?