Java整型转换为字节,以及字节转换为整型

6
我知道在Java中,int类型占用4个字节。但我希望将一个int类型的数值转换成n个字节的数组,其中n可以是1、2、3或4个字节。我想要得到有符号的字节/字节数组,这样即使我需要将它们转换回int类型(即使它只有1个字节),我也能得到相同的有符号整数。我完全意识到从int类型转换为3个或更少字节时可能会存在精度损失的可能性。
我已经成功地将int类型转换为n个字节,但是将其转换回负数时会产生无符号结果。
编辑:
将int类型转换为字节数组(参数n指定所需的字节数,可以是1、2、3或4个字节,无论可能的精度损失如何)。
public static byte[] intToBytes(int x, int n) {
    byte[] bytes = new byte[n];
    for (int i = 0; i < n; i++, x >>>= 8)
        bytes[i] = (byte) (x & 0xFF);
    return bytes;
}

将字节转换为整数(不考虑1、2、3或4个字节)

public static int bytesToInt(byte[] x) {
    int value = 0;
    for(int i = 0; i < x.length; i++)
        value += ((long) x[i] & 0xffL) << (8 * i);
    return value;
}

字节转整数可能存在问题。

3个回答

6
无论如何,这是我拼凑出来的代码:
public static void main(String[] args) throws Exception {
  final byte[] bi = encode(-1);
  System.out.println(Arrays.toString(bi));
  System.out.println(decode(bi));
}
private static int decode(byte[] bi) {
  return bi[3] & 0xFF | (bi[2] & 0xFF) << 8 |
         (bi[1] & 0xFF) << 16 | (bi[0] & 0xFF) << 24;
}
private static byte[] encode(int i) {
  return new byte[] { (byte) (i >>> 24), (byte) ((i << 8) >>> 24),
                      (byte) ((i << 16) >>> 24), (byte) ((i << 24) >>> 24)
  };
}

这仅适用于4个字节,而不是1、2、3或4个字节,并将其转换回整数,正如我在问题中所述。另外,请看看您所要求的内容。谢谢。 - ccit
那么,既然我的代码能够正常工作,是什么阻止你从中获取灵感呢?你需要将你的“+”替换为“|”。顺便说一句,你使用long是不必要的。 - Marko Topolnik
我的代码使用4字节运行,顺便说一下,经过试错后留下了long的使用,我在发布之前应该将其删除。而将“+”替换为“|”并没有改变任何东西。问题出在小于4字节的字节中有负整数。 - ccit
如果int小于4个字节,您需要符号扩展它。或者只需使用BigInteger进行解码。 - Marko Topolnik

6

BigInteger.toByteArray()可以帮助您完成此操作...

返回一个包含此 BigInteger 的二进制补码表示的字节数组。字节数组将以大端字节顺序排列:最重要的字节位于第零个元素中。 数组将包含表示此 BigInteger 所需的最小字节数,包括至少一个符号位,该符号位为 (ceil((this.bitLength() + 1)/8)) (此表示与 (byte[]) 构造函数兼容。)

示例代码:

final BigInteger bi = BigInteger.valueOf(256);
final byte[] bytes = bi.toByteArray();

System.out.println(Arrays.toString(bytes));

输出:

[1, 0]

如果要将字节数组转换回int,请使用BigInteger(byte[])构造函数:

final int i = new BigInteger(bytes).intValue();
System.out.println(i);

这将打印出预期的结果:

256

我知道BigInteger。但是BigInteger返回的是精确字节,而不是像指示的那样1、2、3或4个字节。例如,5始终为1个字节,但我想要选择将其设置为2/3/4个字节的选项。 - ccit
我最终使用了 new BigInteger(bytes).intValue() 来实现我的 bytesToInt - ccit

1

类似这样的:

int unsignedByte = ((int)bytes[i]) & 0xFF;

int n = 0;
n |= unsignedByte << 24;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接