如何在Java中将字节转换为long?

时间:2009-10-19 03:55:31

标签: java

我正在从硬件设备读取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;
}

10 个答案:

答案 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