字节到 "Bit" 数组

Byte to "Bit"array

字节是最小的数字数据类型 java 但昨天我第一次接触字节流,在每个包的开头都会发送一个标记字节,它提供了有关如何处理的进一步说明包裹。字节的每一位都有特定的含义,所以我需要将字节纠缠成它的 8 位。

您可能可以将字节转换为布尔数组或为每种情况创建一个开关,但这当然不是最佳做法。

这在 java 中怎么可能?为什么 java 中没有位数据类型?

因为物理机上不存在位数据类型。您可以在大多数现代计算机上分配的最小分配是一个字节,也称为八位字节或 8 位。当您显示一个位时,您实际上只是通过算术将第一个位从字节中拉出并将其添加到一个仍在使用 8 位 space 的新字节中。如果你想把位数据放在一个字节中,你可以,但无论你使用什么编程语言,它都将至少存储为一个字节。

看看java.util.BitSet。 您可以使用它来解释读取的字节,并可以使用 get 方法检查是否设置了特定位,如下所示:

byte b = stream.read();
final BitSet bitSet = BitSet.valueOf(new byte[]{b});
if (bitSet.get(2)) {
    state.activateComponentA();
} else {
    state.deactivateComponentA();
}
state.setFeatureBTo(bitSet.get(1));

另一方面,您可以轻松创建自己的位掩码,然后将其转换为字节数组(或只是字节):

final BitSet output = BitSet.valueOf(ByteBuffer.allocate(1));
output.set(3, state.isComponentXActivated());
if (state.isY){
    output.set(4);
}
final byte w = output.toByteArray()[0];

您可以将字节加载到 BitSet 中。这种抽象隐藏了操作单个位的血淋淋的细节。

import java.util.BitSet;

public class Bits {
    public static void main(String[] args) {
        byte[] b = new byte[]{10};
        BitSet bitset = BitSet.valueOf(b);
        System.out.println("Length of bitset = " + bitset.length());
        for (int i=0; i<bitset.length(); ++i) {
            System.out.println("bit " + i + ": " + bitset.get(i));
        }
    }
}

$ java Bits
Length of bitset = 4
bit 0: false
bit 1: true
bit 2: false
bit 3: true

你可以要求任何位,但长度告诉你所有超过 length() - 1 的位都设置为 0 (false):

System.out.println("bit 75: " + bitset.get(75));

bit 75: false

How is this possible in java why are there no bit datatypes in java?

大多数 语言中没有位数据类型。大多数 CPU 指令集几乎没有(如果有的话)专门用于寻址单个位的指令。您可以将缺少这些视为(语言或 CPU)复杂性和需求之间的权衡。

操作单个位可以看作是操作多个位的一种特殊情况;和语言以及 CPU 都配备了后者。

非常常见的操作,如测试、设置、清除、反转以及排他或都支持整数基本类型(字节、short/char、int、long),对类型的所有位进行操作立刻。通过适当地选择参数,您可以 select 对哪些位进行操作。

如果您考虑一下,字节数组 位数组,其中位以 8 个为一组进行分组。使用逻辑寻址数组中的单个位相对简单运算符(AND &、OR |、XOR ^ 和 NOT ~)。

例如,测试字节中是否设置了位 N 可以使用带有掩码的逻辑与来完成,其中仅设置要测试的位:

public boolean testBit(byte b, int n) {
    int mask = 1 << n; // equivalent of 2 to the nth power
    return (b & mask) != 0;
}

将其扩展为字节数组也不是什么魔法,每个字节由 8 位组成,因此字节索引只是位数除以 8,该字节内的位数是余数(模 8) :

public boolean testBit(byte[] array, int n) {
    int index = n >>> 3; // divide by 8
    int mask = 1 << (n & 7); // n modulo 8
    return (array[index] & mask) != 0;
}

这是一个示例,希望对你有用!

DatagramSocket socket = new DatagramSocket(6160, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (true) {
    byte[] recvBuf = new byte[26];
    DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
    socket.receive(packet);
    String bitArray = toBitArray(recvBuf);
    System.out.println(Integer.parseInt(bitArray.substring(0, 8), 2)); // convert first byte binary to decimal
    System.out.println(Integer.parseInt(bitArray.substring(8, 16), 2)); // convert second byte binary to decimal
}
public static String toBitArray(byte[] byteArray) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < byteArray.length; i++) {
            sb.append(String.format("%8s", Integer.toBinaryString(byteArray[i] & 0xFF)).replace(' ', '0'));
        }
        return sb.toString();
}