如何将 Int 与无符号字节相互转换

发布于 2024-12-04 08:18:15 字数 440 浏览 1 评论 0原文

我需要将数字转换为无符号字节。该数字始终小于或等于 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。有什么建议吗?

I need to convert a number into an unsigned byte. The number is always less than or equal to 255, and so it will fit in one byte.

I also need to convert that byte back into that number. How would I do that in Java? I've tried several ways and none work. Here's what I'm trying to do now:

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

and now to convert that byte back into the number:

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

Clearly, this does not work. For some reason, it always converts the number into 65. Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

我乃一代侩神 2024-12-11 08:18:15

Java 中的字节总是有符号的。不过,您可以通过将其与 0xFF 进行二进制运算来获取其无符号值:

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

A byte is always signed in Java. You may get its unsigned value by binary-anding it with 0xFF, though:

int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234
万劫不复 2024-12-11 08:18:15

Java 8 提供 Byte.toUnsignedInt 通过无符号转换将 byte 转换为 int。在 Oracle 的 JDK 中,这简单地实现为 return ((int) x) & 0xff; 因为 HotSpot 已经了解如何优化此模式,但它可能会内在化其他虚拟机。更重要的是,不需要任何先验知识就可以理解调用 toUnsignedInt(foo) 的作用。

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

要将 int 转换回 byte,只需使用强制转换:(byte)someInt。由此产生的缩小原始转换将丢弃所有但最后8位。

Java 8 provides Byte.toUnsignedInt to convert byte to int by unsigned conversion. In Oracle's JDK this is simply implemented as return ((int) x) & 0xff; because HotSpot already understands how to optimize this pattern, but it could be intrinsified on other VMs. More importantly, no prior knowledge is needed to understand what a call to toUnsignedInt(foo) does.

In total, Java 8 provides methods to convert byte and short to unsigned int and long, and int to unsigned long. A method to convert byte to unsigned short was deliberately omitted because the JVM only provides arithmetic on int and long anyway.

To convert an int back to a byte, just use a cast: (byte)someInt. The resulting narrowing primitive conversion will discard all but the last 8 bits.

输什么也不输骨气 2024-12-11 08:18:15

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

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

If you just need to convert an expected 8-bit value from a signed int to an unsigned value, you can use simple bit shifting:

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

If using something other than int as the base type, you'll obviously need to adjust the shift amount: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

Also, bear in mind that you can't use byte type, doing so will result in a signed value as mentioned by other answerers. The smallest primitive type you could use to represent an 8-bit unsigned value would be a short.

烏雲後面有陽光 2024-12-11 08:18:15

除了 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

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

然后,如果将 is 转换为 int,它仍然是 -22,因为转换保留了一个数字。

1{24}11101010

b 的转换后的32 位 值与0xFF 执行and 运算。

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

然后您将得到 234 作为答案。

Except char, every other numerical data type in Java are signed.

As said in a previous answer, you can get the unsigned value by performing an and operation with 0xFF. In this answer, I'm going to explain how it happens.

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

If your machine is 32-bit, then the int data type needs 32-bits to store values. byte needs only 8-bits.

The int variable i is represented in the memory as follows (as a 32-bit integer).

0{24}11101010

Then the byte variable b is represented as:

11101010

As bytes are signed, this value represent -22. (Search for 2's complement to learn more about how to represent negative integers in memory)

Then if you cast is to int it will still be -22 because casting preserves the sign of a number.

1{24}11101010

The the casted 32-bit value of b perform and operation with 0xFF.

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

Then you get 234 as the answer.

洒一地阳光 2024-12-11 08:18:15

该解决方案工作正常(谢谢!),但如果您想避免强制转换并将低级工作留给 JDK,您可以使用 DataOutputStream 写入您的 int 并使用 DataInputStream 将它们读回。它们会自动被视为无符号bytes then:

用于将 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();

特别是。对于处理二进制数据格式(例如平面消息格式等)很有用

The solution works fine (thanks!), but if you want to avoid casting and leave the low level work to the JDK, you can use a DataOutputStream to write your int's and a DataInputStream to read them back in. They are automatically treated as unsigned bytes then:

For converting int's to binary bytes;

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

Reading them back in:

// 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. useful for handling binary data formats (e.g. flat message formats, etc.)

ぺ禁宫浮华殁 2024-12-11 08:18:15

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

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

作为底线,对于有符号/无符号转换,最好将 String 排除在外,并按照 @JB 建议使用位操作。

The Integer.toString(size) call converts into the char representation of your integer, i.e. the char '5'. The ASCII representation of that character is the value 65.

You need to parse the string back to an integer value first, e.g. by using Integer.parseInt, to get back the original int value.

As a bottom line, for a signed/unsigned conversion, it is best to leave String out of the picture and use bit manipulation as @JB suggests.

度的依靠╰つ 2024-12-11 08:18:15

尽管为时已晚,我还是想对此发表自己的意见,因为它可能会澄清为什么 JB Nizet 给出的解决方案有效。我自己在字节解析器和字符串转换上偶然发现了这个小问题。
当您从较大尺寸的整数类型复制到较小尺寸的整数类型时,如该 java 文档所说,会发生这种情况:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3
有符号整数到整型 T 的窄化转换会简单地丢弃除 n 个最低位之外的所有位,其中 n 是用于表示类型 T 的位数。此外,还可能丢失有关数值大小的信息,这可能会导致结果值的符号与输入值的符号不同。

你可以确定一个字节是一个整数类型,正如这个java文档所说
https://docs.oracle.com/javase/tutorial/java/ nutsandbolts/datatypes.html
byte:字节数据类型是 8 位有符号二进制补码整数。

因此,在将整数(32 位)转换为字节(8 位)的情况下,只需将该整数的最后一个(最低有效 8 位)复制到给定的字节变量即可。

int a = 128;
byte b = (byte)a; // Last 8 bits gets copied
System.out.println(b);  // -128

故事的第二部分涉及 Java 一元和二元运算符如何提升操作数。
https://docs。 oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
加宽基元转换(第 5.1.2 节)适用于按照以下规则指定转换任一或两个操作数:

如果任一操作数为 double 类型,则另一个操作数将转换为 double。

否则,如果任一操作数的类型为 float,则另一个操作数将转换为 float。

否则,如果任一操作数的类型为 long,则另一个将转换为 long。

否则,两个操作数都转换为 int 类型。

请放心,如果您使用整型 int 和/或更低的类型,它将被提升为 int。

// byte b(0x80) gets promoted to int (0xFF80) by the & operator and then
// 0xFF80 & 0xFF (0xFF translates to 0x00FF) bitwise operation yields 
// 0x0080
a = b & 0xFF;
System.out.println(a); // 128

我也对此摸不着头脑:)。 rgettman 对此有一个很好的答案。
java中的位运算符仅适用于整数和长整型?

Even though it's too late, I'd like to give my input on this as it might clarify why the solution given by JB Nizet works. I stumbled upon this little problem working on a byte parser and to string conversion myself.
When you copy from a bigger size integral type to a smaller size integral type as this java doc says this happens:

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

You can be sure that a byte is an integral type as this java doc says
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html
byte: The byte data type is an 8-bit signed two's complement integer.

So in the case of casting an integer(32 bits) to a byte(8 bits), you just copy the last (least significant 8 bits) of that integer to the given byte variable.

int a = 128;
byte b = (byte)a; // Last 8 bits gets copied
System.out.println(b);  // -128

Second part of the story involves how Java unary and binary operators promote operands.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2
Widening primitive conversion (§5.1.2) is applied to convert either or both operands as specified by the following rules:

If either operand is of type double, the other is converted to double.

Otherwise, if either operand is of type float, the other is converted to float.

Otherwise, if either operand is of type long, the other is converted to long.

Otherwise, both operands are converted to type int.

Rest assured, if you are working with integral type int and/or lower it'll be promoted to an int.

// byte b(0x80) gets promoted to int (0xFF80) by the & operator and then
// 0xFF80 & 0xFF (0xFF translates to 0x00FF) bitwise operation yields 
// 0x0080
a = b & 0xFF;
System.out.println(a); // 128

I scratched my head around this too :). There is a good answer for this here by rgettman.
Bitwise operators in java only for integer and long?

黒涩兲箜 2024-12-11 08:18:15

如果您想使用原始包装类,这可以工作,但默认情况下所有 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));
}

If you want to use the primitive wrapper classes, this will work, but all java types are signed by default.

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));
}
煮酒 2024-12-11 08:18:15

就可读性而言,我更喜欢 Guava 的

  • UnsignedBytes.checkedCast(long) 将有符号数字转换为无符号字节。
  • UnsignedBytes.toInt(byte) 将无符号字节转换为有符号 int。

In terms of readability, I favor Guava's:

  • UnsignedBytes.checkedCast(long) to convert a signed number to an unsigned byte.
  • UnsignedBytes.toInt(byte) to convert an unsigned byte to a signed int.
打小就很酷 2024-12-11 08:18:15

使用 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

Handling bytes and unsigned integers with 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
北陌 2024-12-11 08:18:15

在 Java 7 中

public class Main {
    public static void main(String[] args) {
        byte b =  -2;
        int i = 0 ;
        i = ( b & 0b1111_1111 ) ;
        System.err.println(i);
    }
}

结果:254

in java 7

public class Main {
    public static void main(String[] args) {
        byte b =  -2;
        int i = 0 ;
        i = ( b & 0b1111_1111 ) ;
        System.err.println(i);
    }
}

result : 254

难以启齿的温柔 2024-12-11 08:18:15

我测试过并且理解了。
在Java中,字节是有符号的,所以一个有符号字节中的234是-22,在二进制中是“11101010”,有符号位是“1”,所以用负数表示2的补码,就变成-22。
并使用 0xFF 进行操作,将 234 转换为 2 字节有符号(32 位),保持所有位不变。

我使用 String 来解决这个问题:

int a = 14206;
byte[] b = String.valueOf(a).getBytes();
String c = new String(b);
System.out.println(Integer.valueOf(c));

输出是 14206。

I have tested it and understood it.
In Java, the byte is signed, so 234 in one signed byte is -22, in binary, it is "11101010", signed bit has a "1", so with negative's presentation 2's complement, it becomes -22.
And operate with 0xFF, cast 234 to 2 byte signed(32 bit), keep all bit unchanged.

I use String to solve this:

int a = 14206;
byte[] b = String.valueOf(a).getBytes();
String c = new String(b);
System.out.println(Integer.valueOf(c));

and output is 14206.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文