如何正确使用 ByteBuffer?

Posted

技术标签:

【中文标题】如何正确使用 ByteBuffer?【英文标题】:How to use ByteBuffer properly? 【发布时间】:2013-10-11 06:27:17 【问题描述】:

我正在尝试以 BigEndian 字节顺序格式正确使用 ByteBuffer..

在将其存储到 Cassandra 数据库之前,我尝试将几个字段组合到一个 ByteBuffer 中。

我将写入 Cassandra 的字节数组由三个字节数组组成,如下所述-

short employeeId = 32767;
long lastModifiedDate = "1379811105109L";
byte[] attributeValue = os.toByteArray();

现在,我将 employeeIdlastModifiedDateattributeValue 一起写入单个字节数组,然后将生成的字节数组写入 Cassandra,然后我将拥有我的 C++ 程序,该程序将检索该字节数组来自 Cassandra 的数据,然后对其进行反序列化以从中提取 employeeIdlastModifiedDateattributeValue

为此,我使用了具有 BigEndian 字节顺序格式的 ByteBuffer。

我已经把这段代码放在一起了 -

public static void main(String[] args) throws Exception 

        String text = "Byte Buffer Test";
        byte[] attributeValue = text.getBytes();

        long lastModifiedDate = 1289811105109L;
        short employeeId = 32767;

        int size = 2 + 8 + 4 + attributeValue.length; // short is 2 bytes, long 8 and int 4

        ByteBuffer bbuf = ByteBuffer.allocate(size); 

        bbuf.order(ByteOrder.BIG_ENDIAN);
        bbuf.putShort(employeeId);
        bbuf.putLong(lastModifiedDate);
        bbuf.putInt(attributeValue.length);
        bbuf.put(attributeValue);

        bbuf.rewind();

        // best approach is copy the internal buffer
        byte[] bytesToStore = new byte[size];
        bbuf.get(bytesToStore);

        // write bytesToStore in Cassandra...

        // Now retrieve the Byte Array data from Cassandra and deserialize it...
        byte[] allWrittenBytesTest = bytesToStore;//magicFunctionToRetrieveDataFromCassandra();

        ByteBuffer bb = ByteBuffer.wrap(allWrittenBytesTest);

        bb.order(ByteOrder.BIG_ENDIAN);
        bb.rewind();

        short extractEmployeeId = bb.getShort();
        long extractLastModifiedDate = bb.getLong();
        int extractAttributeValueLength = bb.getInt();
        byte[] extractAttributeValue = new byte[extractAttributeValueLength];

        bb.get(extractAttributeValue); // read attributeValue from the remaining buffer

        System.out.println(extractEmployeeId);
        System.out.println(extractLastModifiedDate);
        System.out.println(new String(extractAttributeValue));


有没有更好的方法来做这件事,就像我现在做的那样?或者我们可以在这里做一些小的改进??

这是我第一次使用 ByteBuffer 所以有点问题...

谁能看一下,让我知道这是否是使用 ByteBuffer 的正确方法?

【问题讨论】:

你希望Cassandra如何确定attributeValue数组的长度? @AlexeiKaigorodov :我不确定,我理解你的问题.. cassandra 是否需要确定 attributeValue 数组的长度?我们只需要存储它然后检索它? 【参考方案1】:

默认顺序始终为 BIG_ENDIAN,因此您不必设置它。此外,当您 wrap() 时已经 rewind() 了。

我不会复制底层数组,而是使用底层数组。

替换

    bbuf.rewind();

    // best approach is copy the internal buffer
    byte[] bytesToStore = new byte[size];
    bbuf.get(bytesToStore);

    byte[] bytesToStore = bbuf.array();

【讨论】:

:非常感谢 Peter.. 我一定会做出这些改变...您认为还有什么不正确的吗?还是想让我改进?感谢您的帮助.. 您可以直接使用 ByteBuffer 来提高性能,而不是使用 byte[] 和堆 ByteBuffer。 对不起,我很困惑..你能提供一个例子,如何根据我的代码做到这一点吗?谢谢。 @TechGeeky 除非 Cassandra 支持直接缓冲区,否则我不会打扰,因为它无济于事。 对此我不确定,但我想现在没问题。还有一件事,反序列化部分怎么样?我们是否也需要做出任何改变?还是反序列化部分看起来不错。?谢谢..

以上是关于如何正确使用 ByteBuffer?的主要内容,如果未能解决你的问题,请参考以下文章

ByteBuffer类学习

Netty基础必备知识,ByteBuffer和ByteBuf底层原理

Netty基础必备知识,ByteBuffer和ByteBuf底层原理

io.netty.ByteBuf writeBytes(java.nio.ByteBuffer src) API说明

如何序列化 ByteBuffer

80-10-015-原理-Java NIO-ByteBuffer