Java boolean[] to byte[] and back

◇◆丶佛笑我妖孽 提交于 2019-12-10 16:58:27

问题


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


回答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.




回答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));
    }
}



回答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;
}



回答4:


Converting from bytes to booleans:

private static boolean[] convertToBooleanArray(byte[] bytes) {
    boolean [] result = new boolean[bytes.length * 8];

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

    return result;
}

Converting from booleans to bytes by cutting off the last few booleans:

/**
 * This will round down to the nearest number of bytes.  So it will chop off the last few booleans.
 * Eg: If there are 9 booleans, then that will be 1 byte, and it will lose the last boolean.
 */
private static byte[] convertToByteArray(boolean[] booleans) {
    byte[] result = new byte[booleans.length/8];

    for (int i=0; i<result.length; i++) {
        int index = i*8;
        byte b = (byte)(
                (booleans[index+0] ? 1<<7 : 0) +
                (booleans[index+1] ? 1<<6 : 0) +
                (booleans[index+2] ? 1<<5 : 0) + 
                (booleans[index+3] ? 1<<4 : 0) +
                (booleans[index+4] ? 1<<3 : 0) +
                (booleans[index+5] ? 1<<2 : 0) + 
                (booleans[index+6] ? 1<<1 : 0) +
                (booleans[index+7] ? 1 : 0));
        result[i] = b;
    }

    return result;
}

Converting from booleans to bytes by padding the last few booleans:

/**
 * This will pad to the nearest number of bytes.  So the last few booleans will be set to the padValue.
 * Eg: If there are 9 booleans, then the last 7 will be added as the padValue (making 16 booleans).
 * 
 * @param booleans
 * @param padValue
 * @return
 */
public static byte[] convertToByteArray(boolean[] booleans, boolean padValue) {
    boolean[] paddedBooleans;
    int remainder = booleans.length % 8;

    // Booleans are already divisible by 8, nothing to pad
    if (remainder == 0) {
        paddedBooleans = booleans;
    }
    // Boolean are not divisible by 8, need to pad
    else {
        int padAmount = 8 - remainder;
        paddedBooleans = Arrays.copyOf(booleans, booleans.length + padAmount);

        for (int i=booleans.length; i<paddedBooleans.length; i++) {
            paddedBooleans[i] = padValue;
        }
    }

    // Convert the boolean array into a byte array
    byte[] result = new byte[paddedBooleans.length/8];

    for (int i=0; i<result.length; i++) {
        int index = i*8;
        byte b = (byte)(
                (paddedBooleans[index+0] ? 1<<7 : 0) +
                (paddedBooleans[index+1] ? 1<<6 : 0) +
                (paddedBooleans[index+2] ? 1<<5 : 0) + 
                (paddedBooleans[index+3] ? 1<<4 : 0) +
                (paddedBooleans[index+4] ? 1<<3 : 0) +
                (paddedBooleans[index+5] ? 1<<2 : 0) + 
                (paddedBooleans[index+6] ? 1<<1 : 0) +
                (paddedBooleans[index+7] ? 1 : 0));
        result[i] = b;
    }

    return result;
}


来源:https://stackoverflow.com/questions/26944282/java-boolean-to-byte-and-back

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!