我们可以在Java中创build无符号字节吗?
我正在尝试转换无符号的有符号字节。 问题是我收到的数据是无符号的,Java不支持无符号字节,所以当它读取数据时,它将它视为有符号的。
我试图通过从堆栈溢出获得以下解决scheme来转换它。
public static int unsignedToBytes(byte a) { int b = a & 0xFF; return b; }
但是,当它再次被转换为字节,我得到相同的签名数据。 我想把这个数据作为parameter passing给只接受一个字节作为参数的Java函数,所以我不能使用任何其他的数据types。 我该如何解决这个问题?
我不确定我是否理解你的问题。
我只是尝试了这一点,并为字节-12(有符号值)它返回整数244(相当于无符号字节值,但types为一个int
):
public static int unsignedToBytes(byte b) { return b & 0xFF; } public static void main(String[] args) { System.out.println(unsignedToBytes((byte) -12)); }
你想要做什么?
Java不允许像C那样将244表示为byte
值。要在Byte.MAX_VALUE
(127)之上表示正整数,您必须使用其他整数types,如short
, int
或long
。
原语在Java中签名的事实与它们在内存/传输中的表示方式无关 – 一个字节仅为8位,您是否将其解释为符号范围取决于您。 没有魔术标志说“这是签名”或“这是无符号的”。
当原语被签名时,Java编译器将会阻止你将高于+127的值赋给一个字节(或者小于-128)。 然而,为了达到这个目的,没有什么可以阻止你向下转换int(或者short)
int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200) byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention) /* * Will print a negative int -56 because upcasting byte to int does * so called "sign extension" which yields those bits: * 1111 1111 1111 1111 1111 1111 1100 1000 (-56) * * But you could still choose to interpret this as +200. */ System.out.println(b); // "-56" /* * Will print a positive int 200 because bitwise AND with 0xFF will * zero all the 24 most significant bits that: * a) were added during upcasting to int which took place silently * just before evaluating the bitwise AND operator. * So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`. * b) were set to 1s because of "sign extension" during the upcasting * * 1111 1111 1111 1111 1111 1111 1100 1000 (the int) * & * 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF) * ======================================= * 0000 0000 0000 0000 0000 0000 1100 1000 (200) */ System.out.println(b & 0xFF); // "200" /* * You would typically do this *within* the method that expected an * unsigned byte and the advantage is you apply `0xFF` only once * and than you use the `unsignedByte` variable in all your bitwise * operations. * * You could use any integer type longer than `byte` for the `unsignedByte` variable, * ie `short`, `int`, `long` and even `char`, but during bitwise operations * it would get casted to `int` anyway. */ void printUnsignedByte(byte b) { int unsignedByte = b & 0xFF; System.out.println(unsignedByte); // "200" }
Java中没有原始的无符号字节。 通常情况下,将其转换为更大的types:
int anUnsignedByte = (int) byte & 0xff;
Java语言不提供任何像unsigned
关键字。 根据语言规范的byte
表示-128 – 127之间的值。例如,如果将一个byte
转换为int
Java将把第一位解释为符号并使用符号扩展 。
也就是说,没有什么能够阻止你将一个byte
看成8位,并将这些位解释为0到255之间的一个值。请记住,你无法做出任何事情来强迫你解释别人的方法。 如果一个方法接受一个byte
,那么该方法接受一个-128到127之间的值,除非另有明确说明。
为了您的方便,以下是一些有用的转化/操作:
转换为/从int
// From int to unsigned byte int i = 200; // some value between 0 and 255 byte b = (byte) i; // 8 bits representing that value
// From unsigned byte to int byte b = 123; // 8 bits representing a value between 0 and 255 int i = b & 0xFF; // an int representing the same value
(或者,如果您使用Java 8+,请使用Byte.toUnsignedInt
。)
parsing/格式化
最好的方法是使用上面的转换:
// Parse an unsigned byte byte b = (byte) Integer.parseInt("200");
// Print an unsigned byte System.out.println("Value of my unsigned byte: " + (b & 0xFF));
算术
二补数expression式“正常工作”的加法,减法和乘法:
// two unsigned bytes byte b1 = (byte) 200; byte b2 = (byte) 15; byte sum = (byte) (b1 + b2); // 215 byte diff = (byte) (b1 - b2); // 185 byte prod = (byte) (b2 * b2); // 225
分部需要手动转换操作数:
byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));
我认为其他答案已经涵盖了内存表示,你如何处理这些取决于你计划如何使用它的上下文。 我将补充说Java 8增加了一些处理无符号types的支持 。 在这种情况下,你可以使用Byte.toUnsignedInt
int unsignedInt = Byte.toUnsignedInt(myByte);
一个侧面说明,如果你想打印出来,你可以说
byte b = 255; System.out.println((b < 0 ? 256 + b : b));
亚当斯基提供了最好的答案,但还不完整,所以请阅读他的回答,因为它解释了我不是的细节。
如果你有一个系统函数需要一个无符号字节传递给它,你可以传递一个有符号的字节,因为它会自动把它作为一个无符号字节。
所以如果一个系统函数需要四个字节,例如192 168 0 1作为无符号字节,你可以传递-64 -88 0 1,并且该函数仍然可以工作,因为将它们传递给函数的行为将会取消它们的签名。
然而,你不太可能有这个问题,因为系统函数被隐藏在跨平台兼容性的类后面,尽pipe一些java.io读取方法返回了无字节的字节。
如果你想看到这个工作,尝试写签名的字节到一个文件,并读取他们作为无符号字节。
如果你有一个必须传递一个有符号字节的函数,如果你传递一个无符号字节,你期望它做什么?
为什么你不能使用任何其他数据types?
无论如何,你可以使用一个字节作为一个无符号的字节,只需要简单的或不需要翻译。 这一切都取决于如何使用它。 你需要澄清你要做什么。
虽然看起来很烦人(来自C),Java并没有在语言中包含无符号字节,但实际上没有什么大不了,因为一个简单的“b&0xFF”操作会在(罕见)字节中产生(签名)字节b的无符号值,实际上需要的情况。 这些位实际上并没有改变 – 只是解释(只有在例如对数值进行一些math运算时才是重要的)。
如果认为你正在寻找这样的东西。
public static char toUnsigned(byte b) { return (char) (b >= 0 ? b : 256 + b); }
Java中没有无符号字节,但是如果你想显示一个字节,你可以这样做,
int myInt = 144; byte myByte = (byte) myInt; char myChar = (char) (myByte & 0xFF); System.out.println("myChar :" + Integer.toHexString(myChar));
输出:
myChar : 90
有关更多信息,请检查如何在Java中显示hex/字节值 。
按照Java中的限制,在当前的数据types格式中,无符号字节几乎是不可能的。 你可以去其他语言的其他库来执行你正在执行的任务,然后你可以使用JNI来调用它们。
如果你想在Java中使用无符号字节,只需从你感兴趣的数字中减去256即可。它将产生二进制补码和一个负值,这是无符号字节中所需的数字。
例:
int speed = 255; //Integer with the desired byte value byte speed_unsigned = (byte)(speed-256); //This will be represented in two's complement so its binary value will be 1111 1111 //which is the unsigned byte we desire.
使用leJOS编程NXT砖块时,您需要使用这种肮脏的黑客技巧。
是和不是。 我一直在挖掘这个问题。 就像我明白这一点:
事实是,java已经签署了interger -128到127 ..可以在java中显示一个未签名的:
public static int toUnsignedInt(byte x) { return ((int) x) & 0xff; }
例如,如果你添加-12有符号数是无符号的,你会得到244.但是你可以在签名时再次使用这个数字,它必须被移回到有符号的地方,它将再次是-12。
如果你尝试添加244到java字节,你会得到outOfIndexException。
干杯..