May 17, 2012

How to read byte buffer in Java

In telecommunications we need to read and analyze raw byte buffers frequently because this is usual representation of a network packet. However there is an issue with the Java language which does not have unsigned integer types. All integer types in Java are signed. So it is not possible just to read a byte and then analyze it.

For example, if we have byte with value 0x96 we will get -106 instead 150. Why does this happen and what to do?

Negative numbers are stored in the memory in two's complement system. According to this approach we need to make the following conversation to write negative number into the memory:
Step 1. invert all bits
Step 2. add 1

For example, let's try to convert a number -6 to the two's complement system representation.
The binary representation of the number 6 is 00000110.
Step 1. After invert conversion we will have 11111001.
Step 2. 11111001 + 1 = 11111010
So the negative number -6 will look in the two's complement system as 11111010. This number corresponds to unsigned byte 250.

Now let's see what Java makes with our number 0x96 or 150. Since there is no unsigned types in Java, this number is considered as number with a sign. Maximum value for signed byte is 127. So Java makes reverse conversion.
The binary representation of the number 0x96 is 10010110.
Step 1. subtract 1:  10010110-1=10010101
Step 2. invert all bits: ~10010101=01101010
01101010 is -106.
That is why Java considers the byte 0x96 as the negative number -106.

How to fix this Java feature? We need to make two things:
1. Convert a byte into int because the maximum value of a signed byte is only 127. At this step Java will fill the high-order bits with 1 to keep the number negative.
2. Then we need to zero high-order bits to get the original value.

The following code does this:

byte b = (byte) 0x96;
int i = (int) b & 0xFF;