2013-08-02 2 views
2

Вот что я хочу сделать, за исключением двух проблем: position() делает абсолютное позиционирование, а не относительное (и аргумент -1 является таким образом незаконным), и вы, по-видимому, не можете связать другой вызов метода после вызов position() - компилятор жалуется, что он не распознает putShort().Java ByteBuffer - относительное перемещение в цепочке звонков?

// 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 

Любые предложения относительно того, как я могу вернуться к чему-то ближе к моей первой попытке?

EDIT: Спасибо за ответы, все они были полезны. Если кому-то интересно, вот что я сделал:

// 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; 
} 

ответ

1

Отсутствует в элегантности тоже:

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

А, ну, я должен попытаться найти свою элегантность где-то в другом месте. Спасибо за лучшее предложение. – RenniePet

1

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

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

+0

Спасибо за ответы. Я думаю, что в итоге я сделаю что-то вроде того, что предлагает Joop. – RenniePet

+0

Я бы остался с тем, что у вас есть сейчас. Его более эффективный, меньший код и как легко следовать его предложению. Без обид Joop, ваше soltion все еще отлично действует. Но я думаю, что Ренни лучше по этим причинам. –

+0

Просто я ненавижу писать код, который для меня не «изящный», что бы это ни значило. Во всяком случае, я опубликовал свой текущий код в качестве редактирования моего вопроса. Еще раз спасибо за указание, что того, чего я хотел, не существует, я очень новичок в Java. – RenniePet

1

метод определения позиции не определен в ByteBuffer. Но в суперклассе Buffer. Таким образом, вам придется явно указывать тип ByteBuffer после вызова метода позиции и до вызова метода 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(); 
+0

ОК, спасибо, теперь я понимаю, почему компилятор не позволил мне связать вызов метода put() после вызова position(). – RenniePet

+0

Я мог бы предложить вам поставить точки ('.') * перед * вызовом метода для удобочитаемости. –

Смежные вопросы