如何找出存储在 ByteBuffer 中的总字节数?

Posted

技术标签:

【中文标题】如何找出存储在 ByteBuffer 中的总字节数?【英文标题】:How to find out total number of bytes stored in ByteBuffer? 【发布时间】:2015-02-27 01:47:12 【问题描述】:

我正在尝试提取存储在我的 ByteBuffer data_record_value 中的总字节数。

下面是我们如何将data_record_value 表示为一个字节数组,然后从 Java 代码写入我们的数据库。

Offset   Length (in bytes)          Purpose

0           2                       - clientId byte array
2           8                       - value of lastModifiedDate
2+8         4                       - length of avroBinaryValue array
2+8+4       Y                       - avroBinaryValue array

这就是我从数据库中提取它的方式 -

ByteBuffer data_record_value = r.getBytes("data_record_value");

// now how do I extract total number of bytes I have stored in data_record_value?

在做了一些研究之后,我发现了多种方法可以提取存储在我的 ByteBuffer data_record_value 中的总字节数,但我不确定哪一种是正确的?

第一种方法是:

byte[] b = new byte[data_record_value.remaining()];
record_value.get(b);

// this will be in bytes right?
System.out.println("Byte Array Length: " + b.length);

第二种方法是:

int numberOfBytesInRecord = data_record_value.limit();

第三种方法是:

int numberOfBytesInRecord = data_record_value.remaining();

但是以上所有方式的数字完全不匹配?我不确定我应该使用哪一个?我需要提取存储在data_record_value 中的总字节数。

为了进行交叉检查,我们可以从data_record_valueByteBuffer 中提取单个字段并计算我们存储的总字节数并与上述任何一种方式进行比较。

// clientId (of two bytes by using short)
short extractClientId = data_record_value.getShort();

// lastModifiedDate ( of 8 bytes which can be long )
long extractLastModifiedDate = data_record_value.getLong();

int extractAvroBinaryValueLength = data_record_value.getInt();

byte[] extractAvroBinaryValue = new byte[extractAvroBinaryValueLength];

data_record_value.get(extractAvroBinaryValue); // read attributeValue from the remaining buffer

System.out.println(extractClientId);
System.out.println(extractLastModifiedDate);
System.out.println(new String(extractAvroBinaryValue));

更新:-

在 ByteBuffer data_record_value 之一上,这是我打印出来的 -

System.out.println("Record Value Capacity: " + data_record_value.capacity());
System.out.println("Record Value Position: " + data_record_value.position());
System.out.println("Record Value Limit: " + data_record_value.limit());
System.out.println("Record Value Remaining: " + data_record_value.remaining());
System.out.println("Record Value: " + data_record_value);

这就是打印出来的 -

Record Value Capacity: 387
Record Value Position: 185
Record Value Limit: 250
Record Value Remaining: 65
Record Value: java.nio.HeapByteBuffer[pos=185 lim=250 cap=387]

【问题讨论】:

【参考方案1】:

当使用ByteBuffer 时,从缓冲区中放入和获取值是有区别的。

当字节被放入缓冲区时,它们被添加到当前位置。如果达到限制,则缓冲区已满。所以position() 显示缓冲区中的数据量,remaining() 显示缓冲区中仍然可以放入多少字节。我在这里假设要考虑的数据从位置 0 开始(通常应该是这种情况)。

当从缓冲区检索字节时,缓冲区通常已“翻转”。这意味着位置设置为 0,限制设置为旧位置。现在position() 返回的值显示了已经检索到的字节数,remaining() 显示了尚未检索到的字节数。


在您的示例中,您会返回一个预先存在的缓冲区。数据库将数据放在这个缓冲区中,并将 position 放在数据的位置,将 limit 放在数据结束后的字节处。所以数据库将数据放入缓冲区,然后翻转缓冲区。

如果position() 未设置为 0,那么数据库可能会使用更高级的方案来缓冲数据,但位置在数据开头和结尾的限制保持不变。

因此,缓冲区中的数据总量由ByteBuffer.remaining() 返回。您使用相对 get 方法从缓冲区中检索任何数据之前。

一旦您开始检索信息,该信息就会丢失(当然有一些方法可以找回它,例如使用mark()reset())。但是,如果您在稍后的过程中需要此信息,您可以简单地将其存储在局部变量或字段中:

int received = buffer.remaining();

【讨论】:

我已经用我在我的data_record_value 之一上所做的示例打印更新了问题。我没有看到位置 0。请参阅我的更新。 感谢您的更新,这意味着我应该使用第一种方式或第三种方式。我说的对吗? 当然,如果你在任何亲戚get之前执行第三种方式。在这种情况下,第一种和第三种方式应该返回相同的值。

以上是关于如何找出存储在 ByteBuffer 中的总字节数?的主要内容,如果未能解决你的问题,请参考以下文章

如何正确使用 ByteBuffer?

基于类似于来自java的ByteBuffer的字节集合

比较 ByteBuffer 中的字节

如何找出 Hive 数据库的总大小

如何将 ByteBuffer 转换为 pdf

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