Java boolean[] to byte[] and back

11,287

Solution 1

You could do it something like this.

public byte[] toBytes(boolean[] input) {
    byte[] toReturn = new byte[input.length / 8];
    for (int entry = 0; entry < toReturn.length; entry++) {
        for (int bit = 0; bit < 8; bit++) {
            if (input[entry * 8 + bit]) {
                toReturn[entry] |= (128 >> bit);
            }
        }
    }

    return toReturn;
} 

This relies on the fact that toReturn will be initialised with all zeroes. Then for each true that we encounter in input, we set the appropriate bit within the appropriate entry in toReturn.

Solution 2

There already exists a class (BitSet) in the standard library to help you do this, you should use that instead of a boolean array. The class allows you to get and set bits and to various logical operations on your boolean values as a group.

eg.

BitSet bits = BitSet.valueOf(bytes); 
boolean third_bit = bits.get(3);
bits.set(5, false);
byte[] new_bytes = bits.toByteArray();

If you really need to use a boolean array then the following will work.

static boolean[] toBooleanArray(byte[] bytes) {
    BitSet bits = BitSet.valueOf(bytes);
    boolean[] bools = new boolean[bytes.length * 8];
    for (int i = bits.nextSetBit(0); i != -1; i = bits.nextSetBit(i+1)) {
        bools[i] = true;
    }
    return bools;
}

static byte[] toByteArray(boolean[] bools) {
    BitSet bits = new BitSet(bools.length);
    for (int i = 0; i < bools.length; i++) {
        if (bools[i]) {
            bits.set(i);
        }
    }

    byte[] bytes = bits.toByteArray();
    if (bytes.length * 8 >= bools.length) {
        return bytes;
    } else {
        return Arrays.copyOf(bytes, bools.length / 8 + (bools.length % 8 == 0 ? 0 : 1));
    }
}

Solution 3

For converting bytes to booleans:

public static boolean [] bytesToBooleans(byte [] bytes){
    boolean [] bools = new boolean[bytes.length * 8];
    byte [] pos = new byte[]{(byte)0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1};

    for(int i = 0; i < bytes.length; i++){
        for(int j = i * 8, k = 0; k < 8; j++, k++){
            bools[j] = (bytes[i] & pos[k]) != 0;
        }
    }

    return bools;
}

Or another method:

public static boolean [] bytesToBooleansAnotherWay(byte [] bytes){
    boolean [] bools = new boolean[bytes.length * 8];

    for(int i = 0; i < bytes.length; i++){
        int j = i * 8;
        bools[j] = (bytes[i] & 0x80) != 0;
        bools[j + 1] = (bytes[i] & 0x40) != 0;
        bools[j + 2] = (bytes[i] & 0x20) != 0;
        bools[j + 3] = (bytes[i] & 0x10) != 0;
        bools[j + 4] = (bytes[i] & 0x8) != 0;
        bools[j + 5] = (bytes[i] & 0x4) != 0;
        bools[j + 6] = (bytes[i] & 0x2) != 0;
        bools[j + 7] = (bytes[i] & 0x1) != 0;
    }

    return bools;
}
Share:
11,287
Admin
Author by

Admin

Updated on June 04, 2022

Comments

  • Admin
    Admin almost 2 years

    I am sending byte[] arrays over a socket connection in Java.

    I have a pretty long boolean[] array, where array.length % 8 == 0.

    I'd like to convert this boolean[] array into a byte[] array with 8 times as few elements, so that I can then send the byte[] over the socket connection.

    The boolean[] array looks like this: 01011010 10101010 01100011 11001010 etc.

    The byte[] in this case should look like this: 0x5A 0xAA 0x63 0xCA.

    I have found some code on another question on how to convert a single byte into a boolean[] array and added a new method to it to convert an entire array here:

    public static boolean[] booleanArrayFromByteArray(byte[] x) {
        boolean[] y = new boolean[x.length * 8];
        int position = 0;
        for(byte z : x) {
            boolean[] temp = booleanArrayFromByte(z);
            System.arraycopy(temp, 0, y, position, 8);
            position += 8;
        }
        return y;
    }
    
    public static boolean[] booleanArrayFromByte(byte x) {
        boolean bs[] = new boolean[4];
        bs[0] = ((x & 0x01) != 0);
        bs[1] = ((x & 0x02) != 0);
        bs[2] = ((x & 0x04) != 0);
        bs[3] = ((x & 0x08) != 0);
        return bs;
    }
    

    I'd like to know if there is a more efficient way of doing this.

    Edit: Thanks

  • Craigo
    Craigo about 8 years
    This will ignore all false booleans. Ie: An array of booleans that are all false, will get an empty byte array.
  • Dunes
    Dunes about 8 years
    Hmm, yes, this will ignore all higher zero bits after the last one bit. Not much effort to create a full sized empty byte array and copy over the bits byte array though.
  • pfurbacher
    pfurbacher about 7 years
    With Java 8, in the "toBooleanArray(...)" method, you could replace the "for" loop with "bits.stream().forEach(bit -> bools[bit] = true);". It's a bit more succinct for the same work. (Not a really big deal, though.)