Java 是否可以通过确定读取量来读取循环中的位?
存在要从中读取的DataInputStream 我遇到了一个特定的算法:Java 是否可以通过确定读取量来读取循环中的位?,java,bit,datainputstream,Java,Bit,Datainputstream,存在要从中读取的DataInputStream 我遇到了一个特定的算法: int[]nmbrs=新int[64] 读取4位无符号整数。为读取的值指定长度 对于(int i=0;i
还请注意,这对(逻辑)位顺序问题很敏感——即,您是从最高有效位到最低有效位还是从其他方式读取位?创建一个
BitInputStream
类,从底层数据输入流
读取位
像这样:
public final class BitInputStream implements Closeable {
private final InputStream in;
private final ByteOrder streamBitOrder;
private int bits;
private byte bitsLeft;
public BitInputStream(InputStream in) {
this(in, ByteOrder.BIG_ENDIAN);
}
public BitInputStream(InputStream in, ByteOrder bitOrder) {
Objects.requireNonNull(in);
Objects.requireNonNull(bitOrder);
this.in = in;
this.streamBitOrder = bitOrder;
}
@Override
public void close() throws IOException {
this.in.close();
}
public int readBit() throws IOException {
if (this.bitsLeft == 0) {
if ((this.bits = this.in.read()) == -1)
throw new EOFException();
this.bitsLeft = 8;
}
int bitIdx = (this.streamBitOrder == ByteOrder.BIG_ENDIAN ? this.bitsLeft - 1 : 8 - this.bitsLeft);
this.bitsLeft--;
return (this.bits >> bitIdx) & 1;
}
public int readInt() throws IOException {
return readInt(Integer.SIZE, this.streamBitOrder);
}
public int readInt(ByteOrder bitOrder) throws IOException {
return readInt(Integer.SIZE, bitOrder);
}
public int readInt(int len) throws IOException {
return readInt(len, this.streamBitOrder);
}
public int readInt(int len, ByteOrder bitOrder) throws IOException {
if (len == 0)
return 0;
if (len < 0 || len > Integer.SIZE)
throw new IllegalArgumentException("Invalid len: " + len + " (must be 0-" + Integer.SIZE + ")");
int value = 0;
if (bitOrder == ByteOrder.BIG_ENDIAN) {
for (int i = 0; i < len; i++)
value = (value << 1) | readBit();
} else {
for (int i = 0; i < len; i++)
value |= readBit() << i;
}
return value;
}
}
是“4.从第1点重复”支持的意思是“重复步骤3.1”,即,如果步骤3(循环的
)暗示了完全相同的内容,则它是完全冗余的。@Andreas它是另一个数组。所以我猜问题是如何做两次。“如何做两次”将逻辑放入一个方法中,并对其进行两次校准:int[]nmbrs=readNumbers(dataStream);int[]nmbrs=读取编号(数据流)
因此,如果前4位(长度值)是数字3,则将64 x 3=192位读入nmbrs
,因此将从流中读取总共4+192=196位,即24.5字节。这是否意味着nmbrs2
的Length
值位于最后一个字节的后半部分?因此,如果它也是值3,那么您将从输入流中总共消耗24.5+24.5=49字节?但是DataInputStream
读取完整字节(或更多)。您无法读取单个位,因此,如果nmbrs
没有消耗多个完整字节(请参阅我之前的评论),那么您不能在DataInputStream
上重复该操作,否则您将丢失处理的最后一个字节中未使用的位。我有点担心结束点。如果不是8的倍数呢?这是你的协议的函数,@Shklyar。发送端在与接收端相同的每字节I/O约束下运行,因此您需要知道它在位流的末尾做什么。但请注意,完成步骤3/3.1并不一定意味着您处于位流的末尾。值LITTLE_ENDIAN
表示0b1010100100001111将被读取为0B1111000010101=0xf095,而不是0x0fa9
public static void main(String[] args) throws Exception {
String bitData = "0101 00001 00001 00010 00011 00101 01000 01101 10101" // 5: 1, 1, 2, 3, 5, 8, 13, 21
+ " 0011 000 001 010 011 100 101 110 111"; // 3: 0, 1, 2, 3, 4, 5, 6, 7
BigInteger bi = new BigInteger(bitData.replaceAll(" ", ""), 2);
System.out.println("0x" + bi.toString(16) + " = 0b" + bi.toString(2));
byte[] byteData = bi.toByteArray();
try (BitInputStream in = new BitInputStream(new ByteArrayInputStream(byteData))) {
int[] nmbrs = readNmbrs(in);
int[] nmbrs2 = readNmbrs(in);
System.out.println(Arrays.toString(nmbrs));
System.out.println(Arrays.toString(nmbrs2));
}
}
private static int[] readNmbrs(BitInputStream in) throws IOException {
int[] nmbrs = new int[8];
int length = in.readInt(4);
for (int i = 0; i < nmbrs.length; i++)
nmbrs[i] = in.readInt(length);
return nmbrs;
}