如何在Java中处理未签名的短/整数/长

如何在Java中处理未签名的短/整数/长,java,groovy,Java,Groovy,我正在读取一个文件格式,其中指定了一些类型是无符号整数和短整数。当我读取这些值时,我将它们作为字节数组获取。我见过的将它们转换为短/长/短的最佳途径如下: ByteBuffer wrapped = ByteBuffer.wrap(byteArray); int x = wrapped.getInt(); ByteBuffer wrapped = ByteBuffer.wrap(byteArray); int signedInt = wrapped.getInt(); long unsigned

我正在读取一个文件格式,其中指定了一些类型是无符号整数和短整数。当我读取这些值时,我将它们作为字节数组获取。我见过的将它们转换为短/长/短的最佳途径如下:

ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int x = wrapped.getInt();
ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int signedInt = wrapped.getInt();
long unsigned = signedInt & 0xffffffffL;
这看起来很容易使未签名整数溢出。有没有更好的方法来处理这种情况


更新:我应该提到我正在使用Groovy,所以我绝对不在乎是否必须使用
BigInteger
之类的东西。我只想最大限度地保证值的完整性。

要保存无符号int/short/byte,需要使用下一个“更大”的类型,即long/int/short。如果您已经在可能溢出的签名类型中保留了该值,则可以通过执行以下操作来完成转换:

int unsignedVal = byteVal & 0xff
如果你只是施放它们,负的一位将被视为,你仍然会以负值结束


如果您必须处理无符号long,则需要“切换”到java.math.biginger。

无符号原语在java中是一个难题

没有干净的方法来处理它们,除了使用更大的字体和更多的位,并注意避免在铸造时自动扩展标志

在您的情况下,您可以这样做:

ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int x = wrapped.getInt();
ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int signedInt = wrapped.getInt();
long unsigned = signedInt & 0xffffffffL;
我通常在某个地方的实用程序类中编写所需的转换,因为它们很容易出错。如果你在任何地方复制并粘贴一个线性转换,最终一个将是错误的

请注意,如果需要无符号long,唯一较大的类型是
BigInteger


如果您需要的不仅仅是简单的转换,我建议使用Guava,因为它有一些处理无符号类型的好类。请参阅文档。

32位值(有符号或无符号)始终可以无损地存储在
int
*中。这意味着从数据安全的角度来看,您不必担心将无符号值放入有符号类型中

对于
byte
s中的8位值、
short
s中的16位值和
long
s中的64位值也是如此

将无符号值读入相应的有符号类型后,可以将其升级为更大类型的有符号值,以便更轻松地使用预期值:

由于没有大于
long
的基元类型,您可以通过biginger,或使用
long
上的方便方法执行无符号操作:

  • BigInteger.valueOf()的值
  • 和朋友


*这要感谢JVM

取决于你想用它们做什么。如果你想使用它们作为实际的数值,你必须读取它们,将它们提升(即分配)到下一个更大的大小,然后屏蔽可能扩展的符号位。很好,我不知道这些是在Java 8中添加的。