ByteBuffer putLong()长达7个字节的值

voj*_*jta 1 java bytebuffer endianness long-integer

我有一个long.我知道这long不是很大.实际上,它可以编码为7个字节的无符号整数.

我想我写longbyte[7]使用ByteBuffer和小端.

这个

long myLong = ... //some value
byte[] myLongBytes = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN).putLong(myLong).array();
Run Code Online (Sandbox Code Playgroud)

IndexOutOfBoundsException当然是投掷.我甚至可以这样做ByteBuffer吗?我应该以不同的方式做吗?

Pet*_*rey 5

你需要一次写一个字节,例如(基于java.nio.Bits)

static private long makeLong(byte b6, byte b5, byte b4,
                             byte b3, byte b2, byte b1, byte b0)
{
    return ((((long)b6 & 0xff) << 48) |
            (((long)b5 & 0xff) << 40) |
            (((long)b4 & 0xff) << 32) |
            (((long)b3 & 0xff) << 24) |
            (((long)b2 & 0xff) << 16) |
            (((long)b1 & 0xff) <<  8) |
            (((long)b0 & 0xff)      ));
}

static long getLongL(ByteBuffer bb, int bi) {
    return makeLong(bb.get(bi + 6),
                    bb.get(bi + 5),
                    bb.get(bi + 4),
                    bb.get(bi + 3),
                    bb.get(bi + 2),
                    bb.get(bi + 1),
                    bb.get(bi    ));
}

private static byte long6(long x) { return (byte)(x >> 48); }
private static byte long5(long x) { return (byte)(x >> 40); }
private static byte long4(long x) { return (byte)(x >> 32); }
private static byte long3(long x) { return (byte)(x >> 24); }
private static byte long2(long x) { return (byte)(x >> 16); }
private static byte long1(long x) { return (byte)(x >>  8); }
private static byte long0(long x) { return (byte)(x      ); }

static void putLongL(ByteBuffer bb, int bi, long x) {
    bb.put(bi + 6, long6(x));
    bb.put(bi + 5, long5(x));
    bb.put(bi + 4, long4(x));
    bb.put(bi + 3, long3(x));
    bb.put(bi + 2, long2(x));
    bb.put(bi + 1, long1(x));
    bb.put(bi    , long0(x));
}
Run Code Online (Sandbox Code Playgroud)

一般来说,我避免像这样进行微优化,因为它增加了微小增益的复杂性恕我直言.如果你想节省空间我建议使用像停止位编码这样的东西,每7位使用一个字节.即long可能只使用1个字节表示小值,但可能会根据需要大得多.

  • 这么简单的任务代码不是太多吗? (2认同)

vlp*_*vlp 5

(假设OP中指示的小端字节顺序)

(假设你想要长存储的56个最低有效位)

long myLong = someLongValue & 0x00FFFFFFFFFFFFFFL;
ByteBuffer bb = ByteBuffer.allocate(xxx).order(ByteOrder.LITTLE_ENDIAN);
Run Code Online (Sandbox Code Playgroud)

选项A:写入64位长,然后删除一个字节

bb.putLong(myLong);
bb.position(bb.position()-1);
Run Code Online (Sandbox Code Playgroud)

for tail write(即这个long是最后一次写入ByteBuffer):

bb.putLong(myLong);
bb.limit(bb.position()-1);
Run Code Online (Sandbox Code Playgroud)

请注意,只有在您可以确保ByteBuffer容量足够大以适应此临时额外字节时,此方法才有效.

这种方法应该没问题的一些示例情况:

  • 这个56位值后面总是跟着另一个字段(那么你确定有一些容量储备)

  • 当您严格使用该ByteBuffer.limit()功能而不是(ab)使用ByteBufferfor舒适的字节数组写入(由您的帖子暗示)

选项B:写出很长的"每个部分"

bb.putInt((int)myLong);
bb.putShort((short)(myLong>>>32));
bb.put((byte)(myLong>>>48));
Run Code Online (Sandbox Code Playgroud)

这每次都有效.

选项C:使用byte []而不是long

您可以考虑使用字节数组而不是长(取决于您的用例).

祝好运!