unsigned bytes in Java byte array - java

This may seem like an easy question, but I'm so confused.
byte[] bArray = new byte[]{(byte) (0x80 & 0xff)};
System.out.println(bArray[0]);
and my output is -128. Why?
How can I rewrite this so that the byte array contains 128?
I thought that the 0xff made it unsigned.
Thanks for your help!

I thought that the 0xff made it unsigned.
Well, it does, sort of - it promotes it to an int, and keeps just the last 8 bits.
However, you're then casting the result of that back to a byte, and a byte in Java is always signed. (It's annoying, but it's the way it is.) So you might as well just have written:
byte[] bArray = { (byte) 0x80 };
The result would be exactly the same.
You're storing the bit pattern you want to store (10000000) so if you're transmitting this elsewhere, you don't need to worry... it's just when you're viewing it as a byte in Java that it's annoying.

Value range of byte according Java Language Specification 4.2.1
For byte, from -128 to 127, inclusive
so there is no way (in Java) that a byte will hold (byte) 128.
You can cast the byte to an int and apply & 0xff to get the unsigned representation of the byte (as an int). But if you cast it back to an byte it will again be interpreted as being a signed value between -128 and 127...
If you are only concerned with printing:
System.out.println(bArray[0] & 0xff);
or, for hexadecimal
System.out.printf("0x%02x\n", bArray[0]);

My answer is attached in the big picture

Related

Issues with OR-ing with bytes in Java?

Let's say I have the following code in java
byte t = (byte) 0b10001000;
byte z = 0b00000000;
z = (byte) (t|z);
You'd think the output would be 10001000, however it ends up being -1111000 in String representation, the - sign being the first 1 of course, making it 11111000. If I do the same code but with the last bit in z as a 1, e.g. 00000001, and I perform the same operation, I get -1110111, or 11110111. I figure this is due to some conversion issue with the negatively signed byte t. Is there any way to avoid this? Is there any way to have 10000000 work the same in an OR operation as 01000000?
Java doesn't have unsigned types, so when you use binary notaion and set the sign bit things will not go as you expect ;-)
To emulate an unsigned type you need to work in the next size up.

How do I convert a Hex value (example: 0xD1) to a unsigned Byte in Java?

I am trying to take hex values and move them into a byte array. When I do this they are not converted how I need them to be. Most of them are converted to negative numbers. For example, after the execution of the C# code "baCommandPDI[0] = 0xD1;", the value of baCommandPDI[0] is "209". This is what I need. No matter what I try in Java, the value is "-47". I need it to be "209" in the byte array, because this byte array is sent out over TCP/IP to some external hardware. The external hardware cannot interpret -47 as 209. It must be 209. I have tried the following code:
int intTemp = 0xD1; After this line is executed the value of intTemp is 209, great!
int intHexValue = 0xD1 & 0xFF; After this line is executed the value of intHexValue is still 209, I don't understand how, but it ia what it is.
baCommand[0] = (byte) intHexValue; After this line is executed the value of baCommand[0] is -47, bad. This is not what I want. Everytime it converts the value to a byte it makes it signed.
Is there any other way I can do this? Can I use 11010001 and some how assign that value to a byte without making it negative?
In Java, bytes are always signed. But like an unsigned byte in another language, 8 bits are still used. The byte representations for 209 (unsigned) and -47 are the same.
1101 0001
The only difference is how Java interprets the most significant bit -- -128 vs. 128 in an unsigned type. The difference is 256, which is the difference between 209 and -47. You can send the value as is, because the bit values are the same, only the interpretations of this bit pattern are different.
If you would like to convert the value -47 to 209 to convince yourself in Java, you can promote the type to a longer primitive type and mask out the last 8 bits. This line will do this is one line, so you can debug and see that the bits are the same and that the unsigned version is equivalent.
int test = baCommandPDI[0] & 0xFF;
Printing/debugging test will let you see the value 209.
Java does not have a concept of unsigned bytes.
To get 209 from 0xD1, try:
0xD1 & 0xFF;

Create unsigned byte for serial port use

I need to write a java program that will send byte through serial port. I am using the rxtx library. The problem is that in Java everything is signed, and in one byte I need to send 0xfc, but in Java this is signed, and it defined as -4. So how can I make an unsigned byte in java, so that in one byte I can send from 0 to 255?
It's fine - you can just cast where required. If you have an API which lets you send bytes, and you send a byte of -4 in Java, the bit pattern will be the same as for an unsigned byte 0xfc.
If you have a value as an int or short in the range 0-255, just cast that to byte, and again it will represent the right bit pattern, even though the value will become negative if the original value was above 127.
This will work
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
For a byte b , b & 0xFF will return the unsigned integer value .. will that be okay for you??

byte.parse() doesn't like 8 bit

This code
byte b = Byte.parseByte("10000000", 2);
throws an exception in Java. This should be -128 or 255.
Byte has 8 bit. Why can't I parse a 8 bit string?
The reason is down to the range of a byte in Java. Bytes are signed, so you can have anything from -128 ("-10000000") through to 127 ("1111111"), but no values outside that range.
The MAX_VALUE of a byte in java (or in C#) is 127 where as 10000000 return 128 which cannot be stored in a byte variable
What you can do treat the value as signed this way.
byte b = (byte) Integer.parseInt("10000000", 2);
Strictly, you passed not eight bits to parse method, but string representation of usual number with radix 2. And it may contain a sign character. Particularly, byte b = Byte.parseByte("-10000000", 2) works nice and gives -128.
That's not an 8-bit string, it's an 8-character string, and it's not being read the way you think it is...
From the MSDN documentation (here), you'll see that byte.Parse accepts strings in the integer format. So, you're trying to parse 10 million, not -1. The exception you're getting gives this away: you should see an OverflowException.
byte.parse("255") gives the effect you expect (byte is unsigned; using -128 also gives an overflow).

Java implicit conversion of int to byte

I am about to start working on something the requires reading bytes and creating strings. The bytes being read represent UTF-16 strings. So just to test things out I wanted to convert a simple byte array in UTF-16 encoding to a string. The first 2 bytes in the array must represent the endianness and so must be either 0xff 0xfe or 0xfe 0xff. So I tried creating my byte array as follows:
byte[] bytes = new byte[] {0xff, 0xfe, 0x52, 0x00, 0x6F, 0x00};
But I got an error because 0xFF and 0xFE are too big to fit into a byte (because bytes are signed in Java). More precisely the error was that the int couldn't be converted to a byte. I know that I could just explicitly convert from int to byte with a cast and achieve the desired result, but that is not what my question is about.
Just to try something out I created a String and called getBytes("UTF-16") then printed each of the bytes in the array. The output was slightly confusing because the first two bytes were 0xFFFFFFFE 0xFFFFFFFF, followed by 0x00 0x52 0x00 0x6F. (Obvisouly the endianness here is different from what I was trying to create above but that is not important).
Using this output I decided to try and create my byte array the same way:
byte[] bytes = new byte[] {0xffffffff, 0xfffffffe, 0x52, 0x00, 0x6F, 0x00};
And strangely enough it worked fine. So my question is, why does Java allow an integer value of 0xFFFFFF80 or greater to be automatically converted to a byte without an explicit cast, but anything equal to or greater than 0x80 requires an explicit cast?
The key thing to remember here is that int in Java is a signed value. When you assign 0xffffffff (which is 2^32 -1), this is translated into a signed int of value -1 - an int cannot actually represent something as large as 0xffffffff as a positive number.
So for values less than 0x80 and greater than 0xFFFFFF80, the resulting int value is between -128 and 127, which can unambiguously be represented as a byte. Anything outside that range cannot be, and needs forcing with an explicit cast, losing data in the process.
If you use a number without a hint (e.g. 1234L for a long) the compiler assumes an integer. The value 0xffffffff is an integer with value -1 which can be cast to byte without a warning.
Because 0xffffffff is the number -1 and -1 can be interpreted as a byte.
0xff is the same as writing 0x000000ff, not 0xffffffff. So that's your issue; the integer is a positive number (255), but the byte (if converted bit-for-bit) would be a negative number (-1). But 0xffffffff is -1 both as an int and as a byte.
Because int are signed and 0xffffffff represent -1, and 0xff represent an integer of value 255, which not lie into -128 (0x80) +127 (0x7f) range of a byte.

Categories

Resources