2 回答
TA贡献1798条经验 获得超3个赞
可以用Java写吗?怎么写呢?
Java 没有提供以小于一个字节的单位执行 I/O 的机制,但您可以在面向字节的 I/O 之上实现它。您需要在读取时一次缓冲一个或多个字节,并跟踪该缓冲区内的位级位置。
另请注意,这对(逻辑)位顺序问题很敏感——即您是从最高位读到最低位还是相反?
TA贡献1776条经验 获得超12个赞
创建一个BitInputStream从底层读取位的类DataInputStream。
像这样:
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;
}
}
测试
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;
}
输出
0x5084432a1b53053977 = 0b10100001000010001000011001010100001101101010011000001010011100101110111
[1, 1, 2, 3, 5, 8, 13, 21]
[0, 1, 2, 3, 4, 5, 6, 7]
添加回答
举报