Java - How to pack or unpack an unsigned integer from a byte array

Published
Updated

When dealing with sockets and streams, sometimes it is necessary to read packed or encoded bytes, shorts, floats, or integers which may be unsigned. The following examples will identify how to convert these unsigned values into a byte array or convert bytes into an unsigned value.

The following examples will produce results in the endianness of the system architecture that you are running it on. If your code is running on x86, this is most likely to be little-endian. To ensure consistent ordering regardless of platform endianness, scroll down to my section on ByteBuffers.

Pack an unsigned integer

Convert an unsigned int 0 - 4,294,967,295 to a 4-byte packed array

/**
 * @param data unsigned int (0 - 4,294,967,295)
 * @return packed byte array [4]
 */
public static byte[] toBytes(final long data) {
    return new byte[] {
        (byte)((data >> 24) & 0xff),
        (byte)((data >> 16) & 0xff),
        (byte)((data >> 8) & 0xff),
        (byte)((data >> 0) & 0xff),
    };
}

Unpack an unsigned integer

Convert a 4-byte packed array to an unsigned integer

/**
 * @param data (byte[4]) 
 * @return unsigned int (0 - 4,294,967,295)
 */
public static long toUInt(final byte[] data) {
    if (data == null || data.length != 4)
        throw new IllegalArgumentException("!= 4 bytes");
    return (long)(
        (long)(data[3] & 0xffL) << 24 |
        (long)(data[2] & 0xffL) << 16 |
        (long)(data[1] & 0xffL) << 8  |
        (long)(data[0] & 0xffL)
         );
}

Pack an unsigned short

Convert an unsigned short 0 - 65,535 and return a 2-byte packed array.

/**
 * @param unsigned short (0 - 65,535)
 * @return (byte[2])
 */
public static byte[] toBytes(final int data) {
    return new byte[] {
        (byte)((data >> 24) & 0xff),
        (byte)((data >> 16) & 0xff),
        (byte)((data >> 8) & 0xff),
        (byte)((data >> 0) & 0xff),
    };
}

Unpack an unsigned short

Convert a 2-byte packed array to an unsigned short

/**
 * @param data (byte[2])
 * @return short (0 - 65,535)
 */
public static int toUShort(final byte[] data) {
    if (data == null || data.length != 2)
        throw new IllegalArgumentException("!= 2 bytes");
    return (int)(
        (int)(data[1] & 0xff) << 8  |
        (int)(data[0] & 0xff)
         );
}

Pack an unsigned byte

Convert an unsigned byte 0 - 255 and return a 1-byte packed array.

/**
 * @param number unsigned byte (0-255)
 * @return (byte[1])
 */
public static byte[] unsignedToBytes(final short number) {
    return new byte[] { (byte) (number & 0xff) };
}

Unpack an unsigned byte

Convert a 1-byte packed array to an unsigned byte

/**
 * @param data (byte[1])
 * @return short (0-255)
 */
public static short toUByte(final byte[] data) {
    if (data == null || data.length != 1)
        throw new IllegalArgumentException("!= 1 byte");
    return (short) (data[0] & 0xff);
}

Pack a float

Convert a float to a 4-byte array

public static byte[] toBytes(final float data) {
    return toBytes(Float.floatToRawIntBits(data));
}

Pack a double

Convert a double to a 8-byte array

public static byte[] toBytes(final double data) {
    return toBytes(Double.doubleToRawLongBits(data));
}

Packing unsigned integers using ByteBuffers

The following code will pack an unsigned integer using the big endian byte order. You can also replace ByteOrder.BIG_ENDIAN with ByteOrder.LITTLE_ENDIAN should you need it.

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
...
long data = 4294967295L;
byte[] bytes = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN).putInt((int)data).array();