ByteBuffer putLong() 用于 long 的 7 字节值
ByteBuffer putLong() for long of 7-byte value
我有一个long
。我知道这个 long
不是很大。它可以被编码为一个无符号整数,实际上是 7 个字节。
我想使用 ByteBuffer
和小字节序将我的 long
写入 byte[7]
。
这个
long myLong = ... //some value
byte[] myLongBytes = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN).putLong(myLong).array();
当然会抛出 IndexOutOfBoundsException
。我什至可以用 ByteBuffer
做到这一点吗?我应该以不同的方式做吗?
如下操作
byte[] myLongBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(myLong).array();
Java long
是 64 位所以 64/8 = 8 字节值所以你没有分配足够的 space 给它。分配 8 个字节,而不是七个。
你需要一次写入一个字节如(基于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));
}
一般来说,我会避免像这样进行微优化,因为它会增加复杂性,而恕我直言。如果你想保存 space 我建议使用像停止位编码这样的东西,它每 7 位使用一个字节。即,long 可能只对小值使用 1 个字节,但可以根据需要使用更大的字节。
(假设 OP 中指示的小端字节顺序)
(假设你想要存储 long 的 56 个最低有效位)
long myLong = someLongValue & 0x00FFFFFFFFFFFFFFL;
ByteBuffer bb = ByteBuffer.allocate(xxx).order(ByteOrder.LITTLE_ENDIAN);
选项 A:写入 64 位长,然后删除一个字节
bb.putLong(myLong);
bb.position(bb.position()-1);
用于尾写(即这个 long 是对 ByteBuffer
的最后一次写入):
bb.putLong(myLong);
bb.limit(bb.position()-1);
请注意,只有当您可以确保 ByteBuffer
容量足够大以容纳这个临时的额外字节时,此方法才有效。
这种方法应该可行的一些示例案例:
这里这个56bit的值后面总是跟着另外一个字段(那你肯定有一些容量储备)
当您严格使用 ByteBuffer.limit()
功能而不是(ab)使用 ByteBuffer
进行舒适的字节数组写入时(这由您的 post )
选项 B:写长 "per partes"
bb.putInt((int)myLong);
bb.putShort((short)(myLong>>>32));
bb.put((byte)(myLong>>>48));
每次都有效。
选项 C:使用 byte[] 而不是 long
您可以考虑使用字节数组而不是 long(取决于您的用例)。
祝你好运!
我有一个long
。我知道这个 long
不是很大。它可以被编码为一个无符号整数,实际上是 7 个字节。
我想使用 ByteBuffer
和小字节序将我的 long
写入 byte[7]
。
这个
long myLong = ... //some value
byte[] myLongBytes = ByteBuffer.allocate(7).order(ByteOrder.LITTLE_ENDIAN).putLong(myLong).array();
当然会抛出 IndexOutOfBoundsException
。我什至可以用 ByteBuffer
做到这一点吗?我应该以不同的方式做吗?
如下操作
byte[] myLongBytes = ByteBuffer.allocate(Long.SIZE / Byte.SIZE).putLong(myLong).array();
Java long
是 64 位所以 64/8 = 8 字节值所以你没有分配足够的 space 给它。分配 8 个字节,而不是七个。
你需要一次写入一个字节如(基于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));
}
一般来说,我会避免像这样进行微优化,因为它会增加复杂性,而恕我直言。如果你想保存 space 我建议使用像停止位编码这样的东西,它每 7 位使用一个字节。即,long 可能只对小值使用 1 个字节,但可以根据需要使用更大的字节。
(假设 OP 中指示的小端字节顺序)
(假设你想要存储 long 的 56 个最低有效位)
long myLong = someLongValue & 0x00FFFFFFFFFFFFFFL;
ByteBuffer bb = ByteBuffer.allocate(xxx).order(ByteOrder.LITTLE_ENDIAN);
选项 A:写入 64 位长,然后删除一个字节
bb.putLong(myLong);
bb.position(bb.position()-1);
用于尾写(即这个 long 是对 ByteBuffer
的最后一次写入):
bb.putLong(myLong);
bb.limit(bb.position()-1);
请注意,只有当您可以确保 ByteBuffer
容量足够大以容纳这个临时的额外字节时,此方法才有效。
这种方法应该可行的一些示例案例:
这里这个56bit的值后面总是跟着另外一个字段(那你肯定有一些容量储备)
当您严格使用
ByteBuffer.limit()
功能而不是(ab)使用ByteBuffer
进行舒适的字节数组写入时(这由您的 post )
选项 B:写长 "per partes"
bb.putInt((int)myLong);
bb.putShort((short)(myLong>>>32));
bb.put((byte)(myLong>>>48));
每次都有效。
选项 C:使用 byte[] 而不是 long
您可以考虑使用字节数组而不是 long(取决于您的用例)。
祝你好运!