2

这就是我想要做的,除了它有两个问题: position() 进行绝对定位,而不是相对定位(因此 -1 的参数是非法的),并且您显然不能在一个位置之后链接另一个方法调用() 调用 - 编译器抱怨它无法识别 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;
}
4

3 回答 3

1

ByteBuffer 中没有定义 position 方法。但是在它的超类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();
于 2013-08-02T13:19:27.123 回答
1

也缺少优雅:

byte[] bytes = ByteBuffer.allocate(4).putInt(totalMessageLength).array();
byteBuffer.put(bytes, 0, 3);
于 2013-08-02T13:22:52.950 回答
1

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

我以为您可以使用mark,但是由于您在一次操作中添加了 4 个字节,因此您无法标记第三个字节以便轻松重置。

于 2013-08-02T13:10:02.890 回答