Java 是否可以通过确定读取量来读取循环中的位?

Java 是否可以通过确定读取量来读取循环中的位?,java,bit,datainputstream,Java,Bit,Datainputstream,存在要从中读取的DataInputStream 我遇到了一个特定的算法: int[]nmbrs=新int[64] 读取4位无符号整数。为读取的值指定长度 对于(int i=0;i

存在要从中读取的DataInputStream

我遇到了一个特定的算法:

  • int[]nmbrs=新int[64]

  • 读取4位无符号整数。为读取的值指定长度

  • 对于(int i=0;i<64;i++)

    3.1将长度位无符号整数读取为nmbrs[i]

  • 可以用Java编写吗?怎么写

    可以用Java编写吗?怎么写

    Java不提供以小于一个字节的单位执行I/O的机制,但您可以在面向字节的I/O之上实现它。您需要在读取时一次缓冲一个或多个字节,并跟踪该缓冲区中的位级位置


    还请注意,这对(逻辑)位顺序问题很敏感——即,您是从最高有效位到最低有效位还是从其他方式读取位?

    创建一个
    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;
    }