Java ByteBuffer - 在put调用链中的相对重新定位?

时间:2013-08-02 12:56:37

标签: java bytebuffer

这是我想要做的,除了它有两个问题:position()执行绝对定位,而不是相对(并且-1的参数因此是非法的),并且您显然无法链接另一个方法调用在position()调用之后 - 编译器抱怨它不识别putShort()。

// Method to create a packet header for sending a packet. The placement of the two numbers is
//  done according to little-endian encoding.
private byte[] createPacketHeader(EPacketType packetType, int fourBits,
                                  int totalMessageLength, int segmentSize) {

    return ByteBuffer.allocate(CPacketHeaderSize).order(ByteOrder.LITTLE_ENDIAN).
            put((byte) ((byte) (packetType.getValue() << 4) | (byte) fourBits)).
            putInt(totalMessageLength).  // Bottom 3 bytes of total length (+ 1 byte discarded)
            position(-1).  // Reposition to discard last byte from above call !!DOESN'T WORK!!
            putShort((short) segmentSize).  // Segment length
            put(_connectIdUtf8).  // Connection ID in UTF-8, should be <= 10 bytes
            array();  // This assumes zero initialization so final bytes are zero
}

所以这就是我目前正在做的事情。它确实有效,但与我希望的相比,看起来相当不优雅。

    ByteBuffer byteBuffer =
                     ByteBuffer.allocate(CPacketHeaderSize).order(ByteOrder.LITTLE_ENDIAN);

    byteBuffer.put((byte) ((byte) (packetType.getValue() << 4) | (byte) fourBits)).
            putInt(totalMessageLength).  // Bottom 3 bytes of total length (+ 1 byte discarded)
            position(byteBuffer.position() -1);  // Discard last byte from above call

    byteBuffer.putShort((short) segmentSize).  // Segment length
            put(_connectIdUtf8);  // Connection ID in UTF-8, should be <= 10 bytes

    return byteBuffer.array();  // This assumes zero initialization so final bytes are zero

有关我如何能够回到第一次接近的事情的任何建议吗?

编辑: 谢谢你的答案,他们都很有帮助。如果有人好奇,这就是我最终做的事情:

// Method to create a packet header for sending a packet. The placement of the two numbers is
//  done according to little-endian encoding.
private byte[] createPacketHeader(EPacketType packetType, int fourBits,
                                  int totalMessageLength, int segmentSize) {

    return ByteBuffer.allocate(CPacketHeaderSize).order(ByteOrder.LITTLE_ENDIAN).
            put((byte) ((byte) (packetType.getValue() << 4) | (byte) fourBits)).
            put(intToThreeBytes(totalMessageLength)).  // Bottom 3 bytes of total length
            putShort((short) segmentSize).  // Segment length
            put(_connectIdUtf8).  // Connection ID in UTF-8, should be <= 10 bytes
            array();  // This assumes zero initialization so final bytes are zero
}


// Method to convert an int into a three-byte byte array, using little-endian encoding
private byte[] intToThreeBytes(int aNumber) {
    byte[] byteArray = new byte[3];
    for (int i = 0; i < 3; i++)
        byteArray[i] = (byte)(aNumber >> i * 8);
    return byteArray;
}

3 个答案:

答案 0 :(得分:1)

我认为你不能。 ByteBuffer只是没有以相对方式递减写入光标的功能。写入光标仅相对增加。

我原以为你可以使用mark,但是当你在一次操作中添加4个字节时,你不能标记第三个字节以便轻松重置。

答案 1 :(得分:1)

位置方法未在ByteBuffer中定义。但在其超级类Buffer中。因此,在调用position方法之后和调用putShort方法之前,您必须显式地对ByteBuffer进行类型转换。更改代码如下:

return ((ByteBuffer)(ByteBuffer.allocate(CPacketHeaderSize).order(ByteOrder.LITTLE_ENDIAN).
        put((byte) ((byte) (packetType.getValue() << 4) | (byte) fourBits)).
        putInt(totalMessageLength).  // Bottom 3 bytes of total length (+ 1 byte discarded)
        position(-1))).  // Reposition to discard last byte from above call !!DOESN'T WORK!!
        putShort((short) segmentSize).  // Segment length
        put(_connectIdUtf8).  // Connection ID in UTF-8, should be <= 10 bytes
        array();

答案 2 :(得分:1)

也缺少优雅:

byte[] bytes = ByteBuffer.allocate(4).putInt(totalMessageLength).array();
byteBuffer.put(bytes, 0, 3);