我正在通过 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;
}
我想知道是否有更有效的方法可以做到这一点。
编辑:谢谢
标准库中已经存在一个类(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));
}
}
你可以这样做。
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
的相应条目中设置适当的位。
要将字节转换为布尔值:
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;
}
从字节转换为布尔值:
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;
}