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();