I am reading 8 bytes of data in from a hardware device. I need to convert them into a numeric value. I think I want to convert them to a long as that should fit 8 bytes. I am not very familiar with Java and low level data type operations. I seem to have two problems (apart from the fact there is almost no documentation for the hardware in question), The bytes are expecting to be unsigned, so I can't do a straight integer conversion. I am not sure what endianness they are.
我正在从硬件设备中读取8字节的数据。我需要把它们转换成数值。我想把它们转换成8字节的长度。我不太熟悉Java和低级别数据类型操作。我似乎有两个问题(除了几乎没有相关硬件的文档之外),字节期望是无符号的,所以我不能进行直接的整数转换。我不确定他们是什么样的意外收获。
Any advice would be appreciated.
如有任何建议,我们将不胜感激。
Ended up with this (taken from some source code I probably should have read a week ago):
结果是这样的(摘自一周前我应该读过的一些源代码):
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;
}
6 个解决方案
#1
1
For the endianness, test with some numbers you know, and then you will be using a byte shifting to move them into the long.
对于机缘凑巧,用一些你知道的数字进行测试,然后您将使用一个字节移位来将它们移动到长。
You may find this to be a starting point. http://www.janeg.ca/scjp/oper/shift.html
你可能会发现这是一个起点。http://www.janeg.ca/scjp/oper/shift.html
The difficulty is that depending on the endianess will change how you do it, but you will shift by 24, 16, 8 then add the last one, basically, if doing 32 bits, but you are going longer, so just do extra shifting.
难点在于依赖于机缘的变化会改变你的工作方式,但是你会移动24 16 8然后加上最后一个,基本上,如果是32位,但是你会变长,所以要做额外的移动。
#2
12
Shifting bytes according to the endianness of the data is fairly straightforward. There is a small trick with the long
datatype, however, because a binary operation on integral types of int
or smaller promotes the operands to int
. For left shifts larger than 31 bits, this will result in zero, since all of the bits have been shifted out of the int
range.
根据数据的意外发现来移动字节相当简单。有小技巧长数据类型,但是,因为一个二元运算的积分类型int或较小的促进操作数int。左大于31位变化,这将导致零,因为所有的碎片已经转移的整数范围。
So, force promotion to long
by including a long
operand in the calculation. Below, I do this by masking each byte with the value 0xFFL, which is a long
, forcing the result to be a long
.
所以,通过在计算中加入长操作数来促进长。下面,我通过使用值0xFFL来屏蔽每个字节,这是一个长值,强制结果是一个长值。
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) ;
#3
5
I believe that you could benefit from using java.nio. This is how you can store 8 bytes in a long:
我相信您可以从使用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();
}
Of course, the resulting longs will have signed representation, but they will have identical binary values to the source data. For a 64 bit+ unsigned representation and arithmatic, you'll need to use BigInteger. Here's how to convert from "unsigned" data stored in a long to a correct BigInteger:
当然,产生的长符号将具有符号表示,但它们将具有与源数据相同的二进制值。对于64位+无符号表示和算术,需要使用BigInteger。以下是如何将长时间存储的“无符号”数据转换为正确的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);
}
#4
4
Byte#longValue() should do it
字节# longValue()应该这样做
And if not (thanks for the source example) you can use java.nio.ByteBuffer such as in
如果没有(感谢源代码示例),可以使用java.nio。ByteBuffer等
public static long toLong(byte[] b) {
ByteBuffer bb = ByteBuffer.allocate(b.length);
bb.put(b);
return bb.getLong();
}
The initial order is BIG_ENDIAN you can reed more here
最初的顺序是BIG_ENDIAN,您可以在这里输入更多
#5
1
Take a look at BigInteger(byte[]). It is almost what you want except that it is a signed one. So you may add one more byte to it before you pass it on to BigInteger.
查看BigInteger(byte[])。它几乎是你想要的,除了它是一个有符号的。因此,您可以在将它传递给BigInteger之前向它添加一个字节。
Another thing is that you should be aware of what endian your bytes are.
另一件事是你应该知道你的字节是什么。
Hope this helps.
希望这个有帮助。
#6
0
If you're reading from an InputStream
, you may also want to look at DataInputStream.readLong(). Java 1.5 introduced Long.reverseBytes(long) which may help you with endianness.
如果您正在阅读InputStream,您可能还想查看DataInputStream.readLong()。Java 1.5引入了long . reversebytes (long),这可能会帮助您使用endianness。
#1
1
For the endianness, test with some numbers you know, and then you will be using a byte shifting to move them into the long.
对于机缘凑巧,用一些你知道的数字进行测试,然后您将使用一个字节移位来将它们移动到长。
You may find this to be a starting point. http://www.janeg.ca/scjp/oper/shift.html
你可能会发现这是一个起点。http://www.janeg.ca/scjp/oper/shift.html
The difficulty is that depending on the endianess will change how you do it, but you will shift by 24, 16, 8 then add the last one, basically, if doing 32 bits, but you are going longer, so just do extra shifting.
难点在于依赖于机缘的变化会改变你的工作方式,但是你会移动24 16 8然后加上最后一个,基本上,如果是32位,但是你会变长,所以要做额外的移动。
#2
12
Shifting bytes according to the endianness of the data is fairly straightforward. There is a small trick with the long
datatype, however, because a binary operation on integral types of int
or smaller promotes the operands to int
. For left shifts larger than 31 bits, this will result in zero, since all of the bits have been shifted out of the int
range.
根据数据的意外发现来移动字节相当简单。有小技巧长数据类型,但是,因为一个二元运算的积分类型int或较小的促进操作数int。左大于31位变化,这将导致零,因为所有的碎片已经转移的整数范围。
So, force promotion to long
by including a long
operand in the calculation. Below, I do this by masking each byte with the value 0xFFL, which is a long
, forcing the result to be a long
.
所以,通过在计算中加入长操作数来促进长。下面,我通过使用值0xFFL来屏蔽每个字节,这是一个长值,强制结果是一个长值。
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) ;
#3
5
I believe that you could benefit from using java.nio. This is how you can store 8 bytes in a long:
我相信您可以从使用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();
}
Of course, the resulting longs will have signed representation, but they will have identical binary values to the source data. For a 64 bit+ unsigned representation and arithmatic, you'll need to use BigInteger. Here's how to convert from "unsigned" data stored in a long to a correct BigInteger:
当然,产生的长符号将具有符号表示,但它们将具有与源数据相同的二进制值。对于64位+无符号表示和算术,需要使用BigInteger。以下是如何将长时间存储的“无符号”数据转换为正确的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);
}
#4
4
Byte#longValue() should do it
字节# longValue()应该这样做
And if not (thanks for the source example) you can use java.nio.ByteBuffer such as in
如果没有(感谢源代码示例),可以使用java.nio。ByteBuffer等
public static long toLong(byte[] b) {
ByteBuffer bb = ByteBuffer.allocate(b.length);
bb.put(b);
return bb.getLong();
}
The initial order is BIG_ENDIAN you can reed more here
最初的顺序是BIG_ENDIAN,您可以在这里输入更多
#5
1
Take a look at BigInteger(byte[]). It is almost what you want except that it is a signed one. So you may add one more byte to it before you pass it on to BigInteger.
查看BigInteger(byte[])。它几乎是你想要的,除了它是一个有符号的。因此,您可以在将它传递给BigInteger之前向它添加一个字节。
Another thing is that you should be aware of what endian your bytes are.
另一件事是你应该知道你的字节是什么。
Hope this helps.
希望这个有帮助。
#6
0
If you're reading from an InputStream
, you may also want to look at DataInputStream.readLong(). Java 1.5 introduced Long.reverseBytes(long) which may help you with endianness.
如果您正在阅读InputStream,您可能还想查看DataInputStream.readLong()。Java 1.5引入了long . reversebytes (long),这可能会帮助您使用endianness。