我正在从硬件设备读取8个字节的数据。我需要将它们转换为数值。我想我想将它们转换为长度,因为它应该适合8个字节。我对Java和低级数据类型操作不是很熟悉。我似乎有两个问题(除了几乎没有相关硬件的文档),字节期望是无符号的,所以我不能进行直接整数转换。我不确定它们是什么字节序。
任何建议都将受到赞赏。
结束了这个(取自我一周前可能应该阅读的一些源代码):
public static final long toLong (byte[] byteArray, int offset, int len)
{
long val = 0;
len = Math.min(len, 8);
for (int i = (len - 1); i >= 0; i--)
{
val <<= 8;
val |= (byteArray [offset + i] & 0x00FF);
}
return val;
}
答案 0 :(得分:12)
根据数据的字节顺序移动字节非常简单。但是,long
数据类型有一个小技巧,因为对int
或更小的整数类型的二进制操作会将操作数提升为int
。对于大于31位的左移,这将导致零,因为所有位都已移出int
范围。
因此,通过在计算中包含long
操作数强制升级到long
。下面,我通过使用值0xFF L (long
)屏蔽每个字节来执行此操作,从而强制结果为long
。
byte[] buf = new byte[8];
/* Fill buf somehow... */
long l = ((buf[0] & 0xFFL) << 56) |
((buf[1] & 0xFFL) << 48) |
((buf[2] & 0xFFL) << 40) |
((buf[3] & 0xFFL) << 32) |
((buf[4] & 0xFFL) << 24) |
((buf[5] & 0xFFL) << 16) |
((buf[6] & 0xFFL) << 8) |
((buf[7] & 0xFFL) << 0) ;
答案 1 :(得分:5)
我相信你可以从使用java.nio中受益。这是你可以在长文件中存储8个字节的方法:
// Byte Array TO Long
public static long batol(byte[] buff) {
return batol(buff, false);
}
public static long batol(byte[] buff, boolean littleEndian) {
assert(buff.length == 8);
ByteBuffer bb = ByteBuffer.wrap(buff);
if (littleEndian) bb.order(ByteOrder.LITTLE_ENDIAN);
return bb.getLong();
}
当然,生成的long将具有签名表示,但它们将具有与源数据相同的二进制值。对于64位+无符号表示和算术,您需要使用BigInteger。以下是如何将存储在long中的“unsigned”数据转换为正确的BigInteger:
// "Unsigned" Long TO Big Integer
public static BigInteger ultobi(long ul) {
byte[] buff = new byte[8];
ByteBuffer.wrap(buff).asLongBuffer().put(ul);
return new BigInteger(+1, buff);
}
答案 2 :(得分:4)
Byte#longValue()应该这样做
如果没有(感谢源代码示例),您可以使用java.nio.ByteBuffer,例如
public static long toLong(byte[] b) {
ByteBuffer bb = ByteBuffer.allocate(b.length);
bb.put(b);
return bb.getLong();
}
初始订单是BIG_ENDIAN,你可以re [{3}}
答案 3 :(得分:1)
对于endianness,使用你知道的一些数字进行测试,然后你将使用字节移位将它们移动到long。
您可能会发现这是一个起点。 http://www.janeg.ca/scjp/oper/shift.html
困难在于取决于结尾会改变你的方式,但是你会改变24,16,8然后加上最后一个,基本上,如果做32位,但是你会更长,所以只做额外转移。
答案 4 :(得分:1)
看看BigInteger(byte [])。这几乎是你想要的,除了它是一个签名的。因此,在将其传递给BigInteger之前,您可以再添加一个字节。
另一件事是你应该知道你的字节是什么字节序。
希望这有帮助。
答案 5 :(得分:1)
ByteBuffer buffer = ByteBuffer.wrap(bytes);
buffer.getLong();
答案 6 :(得分:0)
如果您正在阅读InputStream
,则可能还需要查看DataInputStream.readLong()。 Java 1.5引入了Long.reverseBytes(long),它可以帮助你获得字节序。
答案 7 :(得分:0)
您可以使用:
byte bVal = 127;
Long longVar = Long.valueOf(bVal);
答案 8 :(得分:0)
public static long convertToLong(byte[] array)
{
ByteBuffer buffer = ByteBuffer.wrap(array);
return buffer.getLong();
}
答案 9 :(得分:0)
接下来的代码将字节解析为任意长度≤ 8的有符号数。
static long bytesToSignedNumber(boolean reverseOrder, byte... bytes) {
if (bytes.length > 8) bytes = Arrays.copyOfRange(bytes, 0, 8); //delete this line to ignore the higher excess bytes instead of the lower ones
int l = bytes.length;
long number = 0;
for (int i = 0; i < l; i++) {
long current;
if (l==3 || l==5 || l==6 || l==7 //delete this line if you want to operate with 3,5,6,7-byte signed numbers (unlikely)
|| !reverseOrder && (i > 0)
|| reverseOrder && (i < l-1)) {
current = ((long) bytes[i]) & 0x0000_0000_0000_00ff; //unsigned
} else {
current = (long) bytes[i]; //signed
}
if (reverseOrder) number += current << (8 * i);
else number = (number << 8) + current;
}
return number;
}
它将字节数组解析为一个数字,最小现有类型,转换为long。几个例子:
bytesToSignedNumber(false, 0x01, 0x04)
返回 260
(2 个字节作为 short)
bytesToSignedNumber(false, 0xF1, 0x04)
返回 -3836
(2 个字节作为 short)
bytesToSignedNumber(false, 0x01, 0x01, 0x04)
返回 65796
(3 个字节为 int)
bytesToSignedNumber(false, 0xF1, 0x01, 0x04)
返回 15794436
(3 个字节为 int)
bytesToSignedNumber(false, 0xF1, 0x01, 0x01, 0x04)
返回 -251592444
(4 个字节为 int)
bytesToSignedNumber(false, 0x0F, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04)
返回 1081146489369067777
(9 个字节中的 8 个为 long)