我正在读取一种文件格式,指定某些类型是无符号整数和短整数。当我读取值时,我将它们作为字节数组。我把它们变成短裤/短片/长片的最佳途径是这样的:
ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int x = wrapped.getInt();
对于无符号整数,它看起来很容易溢出。有没有更好的方法来处理这种情况?
更新:我应该提到我使用的是Groovy,所以我绝对不在乎是否必须使用BigInteger
或类似的东西。我只想保持最大值的安全性。
答案 0 :(得分:5)
32位值(有符号或无符号)始终可以无损存储在int
*中。这意味着从数据安全的角度来看,您永远不必担心将无符号值放在有符号的类型中。
byte
中的8位值,short
中的16位值和long
中的64位值也是如此。
一旦您将未签名的值读入相应的签名类型,就可以将它们提升为更大类型的签名值,以便更轻松地使用预期值:
由于没有大于long
的原始类型,您可以通过BigInteger,或使用Long
上的便捷方法进行无符号操作:
*这要归功于JVM需要integer types to be two's complement。
答案 1 :(得分:1)
要保持unsigned int / short / byte,需要使用下一个“更大”类型,即long / int / short。如果您已经保留了可能溢出的签名类型的值,则可以通过执行以下操作来完成转换:
int unsignedVal = byteVal & 0xff
如果您只是投射它们,将会看到负位,您仍然会得到负值。
如果你必须处理unsigned longs,你需要“切换”到java.math.BigInteger。
答案 2 :(得分:1)
无符号原语是Java中的一个难题。
没有干净的方式处理它们,除了使用更多位的更大类型,并注意避免在施法时自动符号扩展。
在您的情况下,您可以执行以下操作:
ByteBuffer wrapped = ByteBuffer.wrap(byteArray);
int signedInt = wrapped.getInt();
long unsigned = signedInt & 0xffffffffL;
我经常在某个地方的实用程序类中编写所需的转换,因为它们很容易出错。如果你复制&粘贴到任何地方的一个班轮转换,最终一个将是错误的。
请注意,如果您需要无符号长整数,则唯一较大的类型为BigInteger
。
如果您需要的不仅仅是简单的转换,我建议使用Guava,因为它有一些很好的类来处理无符号类型。请参阅文档here。