Java ByteBuffer - относительное перепозиционирование в цепочке положенных вызовов?

Вот что я хочу сделать, за исключением двух проблем: position() делает абсолютное позиционирование, а не относительное (и аргумент -1, таким образом, недопустим), и вы, очевидно, не можете связать другой вызов метода после позиции () call - компилятор жалуется, что не распознает 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 ответа

Решение

Также не хватает элегантности:

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

Я не думаю, что ты можешь. ByteBuffer просто не имеет функциональности для уменьшения курсора записи относительным образом. Курсор записи только увеличивается относительно.

Я думал, что вы могли бы использовать mark, но поскольку вы добавляете 4 байта за одну операцию, вы не можете пометить третий для простого сброса.

Метод позиции не определен в ByteBuffer. Но в своем суперклассе Buffer. Таким образом, вам придется явно привести тип к ByteBuffer после вызова метода position и перед вызовом метода putShort. Измените код, как показано ниже:

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();
Другие вопросы по тегам