从2或4个字节转换为有符号/无符号短整型/整型

7

我需要将字节转换为有符号/无符号整数或短整型。

下面的方法正确吗?哪个是有符号的,哪个是无符号的?

字节顺序:LITTLE_ENDIAN

public static int convertTwoBytesToInt1(byte b1, byte b2) {
    return (int) ((b2 << 8) | (b1 & 0xFF));
}

对比。

public static int convertTwoBytesToInt2(byte b1, byte b2) {
    return (int) (( (b2 & 0xFF) << 8) | (b1 & 0xFF));
}

并且

public static int  convertFourBytesToInt1(byte b1, byte b2, byte b3, byte b4){
    return (int) ((b4<<24)+(b3<<16)+(b2<<8)+b1);
}

对比。

public static int  convertFourBytesToInt2(byte b1, byte b2, byte b3, byte b4){
    return (int) (( (b4 & 0xFF) << 24) | ((b3 & 0xFF) << 16) | ((b2 & 0xFF) << 8) | (b1 & 0xFF));
}

我只对这个转换表单感兴趣。谢谢!


1
我会使用ByteBuffer,因为它可以更高效,并且您可以设置.order(ByteOrder.LITTLE_ENDIAN) - Peter Lawrey
2个回答

8
每对方法的第一个(`convertXXXToInt1()`)是带符号的,第二个(`convertXXXToInt2()`)是无符号的。
然而,Java的`int`类型总是带符号的,因此如果`b4`的最高位被设置,则`convertFourBytesToInt2()`的结果将为负数,即使这应该是“无符号”版本。
假设一个`byte`值`b2`为-1,或者十六进制为0xFF。`<<`运算符将其“提升”为一个`int`类型,其值为-1,或者0xFFFFFFFF。经过8位的移位后,它将变为0xFFFFFF00,在移动24位之后,它将变为0xFF000000。
但是,如果应用按位`&`运算符,则高阶位将被设置为零。这将丢弃符号信息。以下是两种情况的前几步详细说明。
带符号:
byte b2 = -1; // 0xFF
int i2 = b2; // 0xFFFFFFFF
int n = i2 << 8; // 0x0xFFFFFF00

无符号:

byte b2 = -1; // 0xFF
int i2 = b2 & 0xFF; // 0x000000FF
int n = i2 << 8; // 0x0000FF00

在 convertFourBytesToInt1 中,b1 没有 &0xff... 所以如果我不加它会有什么区别吗?它仍然是带符号的整数吗? - blackwolf
@blackwolf 实际上,这会有所不同,因为您正在使用 + 运算符组合字节。我之前没有注意到这一点,因为其他人使用了 | 运算符,这是位操作的首选。表达式应该是 (int)((b4<<24) | ((b3 & 0xFF)<<16) | ((b2 & 0xFF)<<8) | (b1 & 0xFF)) - erickson

1

4字节无符号转换存在问题,因为它不能适应int类型。下面的例程可以正确工作。

public class IntegerConversion
{
  public static int convertTwoBytesToInt1 (byte b1, byte b2)      // signed
  {
    return (b2 << 8) | (b1 & 0xFF);
  }

  public static int convertFourBytesToInt1 (byte b1, byte b2, byte b3, byte b4)
  {
    return (b4 << 24) | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
  }

  public static int convertTwoBytesToInt2 (byte b1, byte b2)      // unsigned
  {
    return (b2 & 0xFF) << 8 | (b1 & 0xFF);
  }

  public static long convertFourBytesToInt2 (byte b1, byte b2, byte b3, byte b4)
  {
    return (long) (b4 & 0xFF) << 24 | (b3 & 0xFF) << 16 | (b2 & 0xFF) << 8 | (b1 & 0xFF);
  }

  public static void main (String[] args)
  {
    byte b1 = (byte) 0xFF;
    byte b2 = (byte) 0xFF;
    byte b3 = (byte) 0xFF;
    byte b4 = (byte) 0xFF;

    System.out.printf ("%,14d%n", convertTwoBytesToInt1 (b1, b2));
    System.out.printf ("%,14d%n", convertTwoBytesToInt2 (b1, b2));

    System.out.printf ("%,14d%n", convertFourBytesToInt1 (b1, b2, b3, b4));
    System.out.printf ("%,14d%n", convertFourBytesToInt2 (b1, b2, b3, b4));
  }
}

b1 & 0xFF 是什么意思? - Scorb
@ScottF - 为了防止负值。 - dmolony

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