it-swarm.cn

如何将Int转换为无符号字节和后退

我需要将一个数字转换为无符号字节。该数字始终小于或等于255,因此它将适合一个字节。

我还需要将该字节转换回该数字。我怎么用Java做到这一点?我尝试了几种方法而且都没有用。这就是我现在要做的事情:

int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);

现在将该字节转换回数字:

Byte test = new Byte(binaryByte);
int msgSize = test.intValue();

显然,这不起作用。出于某种原因,它总是将数字转换为65。有什么建议?

78
darksky

始终用Java签名一个字节。您可以通过二进制获取其无符号值,并使用0xFF,但是:

int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
180
JB Nizet

Java 8提供 Byte.toUnsignedInt 通过无符号转换将byte转换为int。在Oracle的JDK中,这只是作为return ((int) x) & 0xff;实现的,因为HotSpot已经了解如何优化这种模式,但它可以在其他VM上进行内在化。更重要的是,不需要先验知识来理解对toUnsignedInt(foo)的调用。

总的来说,Java 8提供了将byteshort转换为unsigned intlong,以及int转换为unsigned long的方法。将byte转换为无符号short的方法是 故意省略 因为JVM只提供intlong的算术。

要将int转换回字节,只需使用强制转换:(byte)someInt。结果 缩小基元转换 将丢弃除最后8位之外的所有内容。

42
Jeffrey Bosboom

如果您只需要将有符号的int的预期8位值转换为无符号值,则可以使用简单的位移:

int signed = -119;  // 11111111 11111111 11111111 10001001

/**
 * Use unsigned right shift operator to drop unset bits in positions 8-31
 */
int psuedoUnsigned = (signed << 24) >>> 24;  // 00000000 00000000 00000000 10001001 -> 137 base 10

/** 
 * Convert back to signed by using the sign-extension properties of the right shift operator
 */
int backToSigned = (psuedoUnsigned << 24) >> 24; // back to original bit pattern

http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/op3.html

如果使用int以外的其他东西作为基本类型,你显然需要调整移位量: http://docs.Oracle.com/javase/tutorial/Java/nutsandbolts/datatypes.html

另外,请记住,您不能使用byte类型,这样做会导致其他回答者提到的签名值。可用于表示8位无符号值的最小基本类型将是short

7
dm78

Integer.toString(size)调用转换为整数的char表示,即char '5'ASCII表示 该字符的值是值65。

您需要首先将字符串解析回整数值,例如通过使用 Integer.parseInt 来获取原始的int值。

作为底线,对于有符号/无符号转换,最好将String从图片中删除,并使用位操作,如@JB所示。

3
Péter Török

解决方案工作正常(谢谢!),但是如果你想避免强制转换并将低级别的工作留给JDK,你可以使用DataOutputStream来编写你的int和DataInputStream来重新读取它们。它们会被自动视为unsigned字节然后:

用于将int转换为二进制字节;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
int val = 250;
dos.write(byteVal);
...
dos.flush();

读回来:

// important to use a (non-Unicode!) encoding like US_ASCII or ISO-8859-1,
// i.e., one that uses one byte per character
ByteArrayInputStream bis = new ByteArrayInputStream(
   bos.toString("ISO-8859-1").getBytes("ISO-8859-1"));
DataInputStream dis = new DataInputStream(bis);
int byteVal = dis.readUnsignedByte();

ESP。用于处理二进制数据格式(例如扁平消息格式等)

2
Gregor

使用BigInteger处理字节和无符号整数:

byte[] b = ...                    // your integer in big-endian
BigInteger ui = new BigInteger(b) // let BigInteger do the work
int i = ui.intValue()             // unsigned value assigned to i
1
pgrandjean

除了char之外,Java中的每个其他数值数据类型都是有符号的。

如前面的答案中所述,您可以通过0xFF执行and操作来获取无符号值。在这个答案中,我将解释它是如何发生的。

int i = 234;
byte b = (byte) i;
System.out.println(b);  // -22

int i2 = b & 0xFF;      
// This is like casting b to int and perform and operation with 0xFF

System.out.println(i2); // 234

如果您的机器是32位,则int数据类型需要32位来存储值。 byte只需要8位。

int变量i在内存中表示如下(作为32位整数)。

0{24}11101010

那么byte变量b表示为:

11101010

由于bytes是无符号的,因此该值表示-22。 (搜索2的补码以了解有关如何在内存中表示负整数的更多信息)

然后,如果你施放的是int,那么它仍然是-22,因为施放会保留数字的符号。

1{24}11101010

b的转换32-bit值使用0xFF执行and操作。

 1{24}11101010 & 0{24}11111111
=0{24}11101010

然后你得到234作为答案。

0
Ramesh-X

如果要使用原始包装类,这将起作用,但默认情况下会对所有Java类型进行签名。

public static void main(String[] args) {
    Integer i=5;
    Byte b = Byte.valueOf(i+""); //converts i to String and calls Byte.valueOf()
    System.out.println(b);
    System.out.println(Integer.valueOf(b));
}
0
Romeo