【问题标题】:Java boolean[] to byte[] and backJava boolean[] 到 byte[] 并返回
【发布时间】:2023-03-20 09:03:01
【问题描述】:

我通过 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 循环和|= 适当地填充它们。
  • 为什么你的booleanArrayFromByte(byte) 只返回 4 位?
  • @ElliottFrisch 好点。我忘记改了
  • 请查看我的答案,更短更高效的解决方案。

标签: java arrays boolean byte bytearray


【解决方案1】:

从字节转换为布尔值:

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

【讨论】:

    【解决方案2】:

    标准库中已经存在一个类 (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));
        }
    }
    

    【讨论】:

    • 这将忽略所有错误的布尔值。即:一个全部为假的布尔数组,将得到一个空字节数组。
    • 嗯,是的,这将忽略最后一位之后的所有高零位。不过,创建一个完整大小的空字节数组并复制位字节数组并不费力。
    • 使用 Java 8,在“toBooleanArray(...)”方法中,您可以将“for”循环替换为“bits.stream().forEach(bit -> bools[bit] =真的);”。对于相同的工作,它更简洁一些。 (不过没什么大不了的。)
    【解决方案3】:

    用于将字节转换为布尔值:

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

    【讨论】:

      【解决方案4】:

      你可以这样做。

      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 的相应条目中设置相应的位。

      【讨论】:

        猜你喜欢
        • 2013-03-08
        • 2011-05-27
        • 1970-01-01
        • 1970-01-01
        • 2013-10-24
        • 1970-01-01
        • 1970-01-01
        • 2020-05-07
        相关资源
        最近更新 更多