如何将 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
。有什么建议吗?
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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
Java 中的字节总是有符号的。不过,您可以通过将其与 0xFF 进行二进制运算来获取其无符号值:
A byte is always signed in Java. You may get its unsigned value by binary-anding it with 0xFF, though:
Java 8 提供
Byte.toUnsignedInt
通过无符号转换将byte
转换为int
。在 Oracle 的 JDK 中,这简单地实现为 return ((int) x) & 0xff; 因为 HotSpot 已经了解如何优化此模式,但它可能会内在化其他虚拟机。更重要的是,不需要任何先验知识就可以理解调用toUnsignedInt(foo)
的作用。总的来说,Java 8 提供了将
byte
和short
转换为无符号int
和long
以及的方法。 int
到无符号long
。将byte
转换为无符号short
的方法是故意省略,因为 JVM 只提供int
和long
的算术运算。要将 int 转换回 byte,只需使用强制转换:
(byte)someInt
。由此产生的缩小原始转换将丢弃所有但最后8位。Java 8 provides
Byte.toUnsignedInt
to convertbyte
toint
by unsigned conversion. In Oracle's JDK this is simply implemented asreturn ((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 totoUnsignedInt(foo)
does.In total, Java 8 provides methods to convert
byte
andshort
to unsignedint
andlong
, andint
to unsignedlong
. A method to convertbyte
to unsignedshort
was deliberately omitted because the JVM only provides arithmetic onint
andlong
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.如果您只需要将预期的 8 位值从有符号 int 转换为无符号值,则可以使用简单的位移位:
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:
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.htmlAlso, 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 ashort
.除了
char
之外,Java 中的所有其他数字数据类型都是有符号的。正如之前的答案中所述,您可以通过使用
0xFF
执行and
运算来获取无符号值。在这个答案中,我将解释它是如何发生的。如果您的机器是 32 位,则
int
数据类型需要 32 位来存储值。byte
只需要 8 位。int
变量i
在内存中表示如下(作为 32 位整数)。那么
byte
变量b
表示为:由于
byte
有符号,该值表示-22
。 (搜索 2 的补码以了解有关如何在内存中表示负整数的更多信息)然后,如果将 is 转换为
int
,它仍然是-22
,因为转换保留了一个数字。b
的转换后的32 位
值与0xFF
执行and
运算。然后您将得到
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 with0xFF
. In this answer, I'm going to explain how it happens.If your machine is 32-bit, then the
int
data type needs 32-bits to store values.byte
needs only 8-bits.The
int
variablei
is represented in the memory as follows (as a 32-bit integer).Then the
byte
variableb
is represented as:As
byte
s 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.The the casted
32-bit
value ofb
performand
operation with0xFF
.Then you get
234
as the answer.该解决方案工作正常(谢谢!),但如果您想避免强制转换并将低级工作留给 JDK,您可以使用 DataOutputStream 写入您的 int 并使用 DataInputStream 将它们读回。它们会自动被视为无符号bytes then:
用于将 int 转换为二进制字节;
读回它们:
特别是。对于处理二进制数据格式(例如平面消息格式等)很有用
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;
Reading them back in:
Esp. useful for handling binary data formats (e.g. flat message formats, etc.)
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.尽管为时已晚,我还是想对此发表自己的意见,因为它可能会澄清为什么 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 位)复制到给定的字节变量即可。
故事的第二部分涉及 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。
我也对此摸不着头脑:)。 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.
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.
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?
如果您想使用原始包装类,这可以工作,但默认情况下所有 java 类型都是签名的。
If you want to use the primitive wrapper classes, this will work, but all java types are signed by default.
就可读性而言,我更喜欢 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.使用 BigInteger 处理字节和无符号整数:
Handling bytes and unsigned integers with BigInteger:
在 Java 7 中
结果:254
in java 7
result : 254
我测试过并且理解了。
在Java中,字节是有符号的,所以一个有符号字节中的234是-22,在二进制中是“11101010”,有符号位是“1”,所以用负数表示2的补码,就变成-22。
并使用 0xFF 进行操作,将 234 转换为 2 字节有符号(32 位),保持所有位不变。
我使用 String 来解决这个问题:
输出是 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:
and output is 14206.