Main Tutorials

Java – Convert bytes to unsigned bytes

In Java, byte is an 8-bit signed (positive and negative) data type, values from -128 (-2^7) to 127 (2^7-1). For unsigned byte, the allowed values are from 0 to 255.

Java doesn’t have unsigned bytes (0 to 255). To make an unsigned byte, we can cast the byte into an int and mask (bitwise and) the new int with a 0xff to get the last 8 bits or prevent sign extension.


  byte aByte = -1;
  int number = aByte & 0xff;  // bytes to unsigned byte in an integer.

Why cast byte to int?
Java uses two’s complement to represent signed numbers (positive and negative), the leftmost bit denotes the sign (0 is positive, 1 is negative), the rest of the bits represents the values from -128 (-2^7) to 127 (2^7-1), the so-called 8-bit byte only have 7 bits to store the values. The extra values (128 – 255) are unable to fit into a single byte, and we cast it to a 32-bit unsigned integer for more spaces (bits).

Prerequisite

1. Bytes to Unsigned Byte

1.1 Review the following table for the byte to unsigned byte (int) conversion:

Byte Unsigned Byte
1 1
2 2
127 127
-128 128
-127 129
-126 130
-2 254
-1 255

1.2 First, we cast the byte 8-bit into an int 32-bit.

For example, byte -1 in two’s complement, the binary is 1111 1111.


# two's complement formula to convert positive to negative
# leftmost bit, 1 is negative, 0 is positive

0000 0001 (1)
1111 1110 (invert bits)
1111 1111 (add 1)
1111 1111 (-1)

When we convert or upcast a byte to an int, it will increase the bits from 8 to 32. The sign extension will apply and fill in the values of the increased bits.


1111 1111 (-1)

byte -> int
???? ???? | ???? ???? | ???? ???? | 1111 1111

sign extension
1111 1111 | 1111 1111 | 1111 1111 | 1111 1111

1.3 Now, we perform a bitwise and or & with a 0xff to get the last 8 bits.


1111 1111 | 1111 1111 | 1111 1111 | 1111 1111  (int -1)
&
0000 0000 | 0000 0000 | 0000 0000 | 1111 1111  (0xff)
=
0000 0000 | 0000 0000 | 0000 0000 | 1111 1111  (last 8 bits)

1.4 Binary to decimal calculation.


1  1  1  1  1   1   1    1
1, 2, 4, 8, 16, 32, 64, 128 = 255

Done. For -1 , now we have 255.


  byte aByte = -1;
  int number = aByte & 0xff;
  System.out.println(number);  // output = 255

2. Java 8

Java 8 introduced many new APIs to support unsigned operations, for byte, now we have Byte.toUnsignedInt() to convert a signed byte into an unsigned integer.

Java8UnsignedByte.java

package com.mkyong.crypto.bytes;

public class Java8UnsignedByte {

    public static void main(String[] args) {

        byte aByte = (byte) -2;                              // -2 (signed) and 254 (unsigned)
        System.out.println(aByte);                           // -2

        // Java 8
        System.out.println(Byte.toUnsignedInt(aByte));       // 254

    }
}

Review the new Byte.toUnsignedInt; Java 8 uses the same technique to convert a byte to an unsigned integer.

Byte.java

public final class Byte extends Number implements Comparable<Byte> {

  /*
  @since 1.8
  */
  public static int toUnsignedInt(byte x) {
        return ((int) x) & 0xff;
  }

3. Old Java + Comments

This Java example is using the same technique, with inline comments. Read for self-explanatory.

JavaUnsignedByte

package com.mkyong.crypto.bytes;

public class JavaUnsignedByte {

    public static void main(String[] args) {

        byte input = (byte) -2;                         // -2 (signed) and 254 (unsigned)

        // -2 = 1111 1110 , two's complement
        System.out.println("Input : " + input);

        // byte (8 bits) cast / widen to int (4 bytes, 16 bits), sign extension will apply
        // 1111 1111 | 1111 1111 | 1111 1111 | 1111 1110
        int input2 = (int) input;

        System.out.println("Input [Binary] : " + Integer.toBinaryString(input2));

        // 1111 1111 | 1111 1111 | 1111 1111 | 1111 1110
        // &
        // 0000 0000 | 0000 0000 | 0000 0000 | 1111 1111 (0xFF) , get last 8 bits
        // =============================================
        // 0000 0000 | 0000 0000 | 0000 0000 | 1111 1110  unsigned int
        int result = input2 & 0xff;

        System.out.println(result); // 254
        System.out.println(Integer.toBinaryString(result)); // 1111 1110

    }
}

References

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
2 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
David
3 years ago

When we convert or upcast a byte to an int, it will increase the bits from 8 to 32. The sign extension will apply and fill in the values of the increased bits.” That’s the moment the penny dropped for me, and the universe made sense again. Thankyou.

Oleh
3 years ago

Thanks. Helped me a lot