如何在Java中将一个字节转换为一个长字节?

时间:2022-10-30 14:54:43

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。