I felt like programming something this afternoon.
The class BitReader
below allows you to either read at most 8 bits at a time through the readBits
method, or 17 bits in one go through the readBits17
method.
Source code
public class BitReader {
private static final int[] MASK = new int[16];
static {
for (int i = 0; i < 16; i++) {
MASK[i] = (1 << i) - 1;
}
}
private InputStream in;
private int bitsLeft;
private int bitBuffer;
public BitReader(InputStream in) {
this.in = in;
}
/**
* Reads at most 8 bits from the InputStream.
*
* @param bits
* between 1 and 8 (inclusive)
*/
public int readBits(int bits) throws IOException {
if (bits < 1 && bits > 8)
throw new IllegalArgumentException("bits");
if (bits > bitsLeft) {
int r = in.read();
if (r == -1) {
throw new EOFException();
}
bitsLeft += 8;
bitBuffer = (bitBuffer << 8) | r;
}
int result = bitBuffer >> (bitsLeft - bits);
bitsLeft -= bits;
bitBuffer &= MASK[bitsLeft];
return result;
}
public int readBits17() throws IOException {
return readBits(8) << 9 | readBits(8) << 1 | readBits(1);
}
}
The class Test
just shows how to use BitReader
.
public class Test {
public static void main(String[] args) throws IOException {
// 1 00000010 01000011 = 65536 + 2 * 256 + 67 = 66115
// Creating a stream that repeats this number twice
// 10000001 00100001 1, 10000001 00100001 1
// 10000001 00100001 11000000 10010000 11[000000] = 129, 33, 192, 144, 192
byte[] data = { (byte) 129, 33, (byte) 192, (byte) 144, (byte) 192 };
ByteArrayInputStream in = new ByteArrayInputStream(data);
BitReader br = new BitReader(in);
// Should print 66115, 66115, 0
System.out.println(br.readBits17());
System.out.println(br.readBits17());
System.out.println(br.readBits(6));
}
}
(Copyright: I hereby place this code in the public domain, for everyone to use as they see fit.)