Java boolean[] 转换为 byte[] 并返回

4

我正在使用Java通过套接字连接发送byte[]数组。

我有一个相当长的boolean[]数组,其中array.length % 8 == 0

我想将这个boolean[]数组转换成一个元素数量少8倍的byte[]数组,以便我可以将byte[]发送到套接字连接上。

boolean[]数组看起来像这样:01011010 10101010 01100011 11001010等等。

在这种情况下,byte[]应该像这样:0x5A 0xAA 0x63 0xCA

我在另一个问题中找到了一些代码来将单个byte转换为boolean[]数组,并添加了一个新方法来在此处将整个数组转换:

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

我想知道是否有更有效的方法来完成这个任务。

编辑:谢谢。


反转就是…嗯,反转。你分配一个大小为x.length / 8字节的数组,并使用for循环和|=适当地填充它们。 - The Paramagnetic Croissant
1
为什么你的 booleanArrayFromByte(byte) 只返回 4 位? - Elliott Frisch
@ElliottFrisch 好观点。我忘记改了。 - user2714958
1
请检查我的答案,是否有更简短和高效的解决方案。 - brb tea
4个回答

6

标准库中已经存在一个类(BitSet),可以帮助您完成此操作,您应该使用该类而不是布尔数组。该类允许您获取和设置位,并对您的布尔值进行各种逻辑操作。

例如:

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

如果您确实需要使用布尔数组,则以下内容可行。
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));
    }
}

2
这将忽略所有的假布尔值。例如:一个由全部为假的布尔值组成的数组,将得到一个空的字节数组。 - Craigo
1
嗯,是的,这将忽略最后一个一位之后的所有高零位。不过创建一个完整大小的空字节数组并复制位字节数组并不需要太多的努力。 - Dunes
在Java 8中,“toBooleanArray(...)”方法中,您可以使用“bits.stream()。forEach(bit-> bools [bit] = true);”替换“for”循环。对于相同的工作来说,这更加简洁。(虽然并不是非常重要。) - pfurbacher

3
你可以像这样做。
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;
} 

这取决于这样一个事实: toReturn 将被初始化为全零。然后,对于我们在input中遇到的每个true,我们会在toReturn中设置相应的位于相应条目中。

2

将字节转换为布尔值:

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

或者另一种方法:
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;
}

0

将字节转换为布尔值:

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

将布尔值转换为字节,通过截断最后几个布尔值:
/**
 * 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;
}

通过填充最后几个布尔值将布尔值转换为字节:

/**
 * 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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接