BitArrayInputStream

Sometime you just have to read the bits one by one at least now you don’t need to write your own class to do it. This class works for ‘Little Endian’ or ‘Big Endian’.

import java.io.IOException;
import java.io.InputStream;

public class BitArrayInputStream {

	private final BitDirection direction;
	private final InputStream inputStream;
	private int currentByte;
	private int currentPosition = -1;

	public BitArrayInputStream(InputStream inputStream) {
		this(BitDirection.HIGHLOW, inputStream);
	}

	public BitArrayInputStream(BitDirection direction,
			InputStream inputStream) {
		this.inputStream = inputStream;
		this.direction = direction;
	}

	public int readBit() throws IOException {
		if(currentPosition == -1) {
			currentByte = inputStream.read();
			if(currentByte == -1) {
				return -1;
			}
			currentPosition = 0;
		}

		int c = -1;

		if(direction.equals(BitDirection.HIGHLOW)) {
			c = (currentByte << currentPosition & 0x80) >> 7;
		} else {
			c = currentByte >> currentPosition & 0x1;
		}

		currentPosition += 1;
		if(currentPosition >= 8) {
			currentPosition = -1;
		}

		return c;
	}

	public static enum BitDirection {HIGHLOW, LOWHIGH}

}

And here is a unit test for it:

public class BitArrayInputStreamTest extends TestCase {

	public void testInit() throws Exception {
		assertNotNull(new BitArrayInputStream(null));
	}

	public void testReadBits() throws Exception {
		BitArrayInputStream i = new BitArrayInputStream(
				new ByteArrayInputStream(new byte[] {(byte) 0xA3}));

		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());

		assertEquals(0, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());


	}

	public void testReadBitsLowHigh() throws Exception {
		BitArrayInputStream i = new BitArrayInputStream(BitDirection.LOWHIGH,
				new ByteArrayInputStream(new byte[] {(byte) 0xA3}));

		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(0, i.readBit());

		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());


	}

	public void testReadBitsEnd() throws Exception {
		BitArrayInputStream i = new BitArrayInputStream(
				new ByteArrayInputStream(new byte[] {(byte) 0xA3}));

		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());

		assertEquals(0, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());

		assertEquals(-1, i.readBit());


	}

	public void testReadBitsMultiByte() throws Exception {
		BitArrayInputStream i = new BitArrayInputStream(
				new ByteArrayInputStream(
                                  new byte[] {(byte) 0xA3, (byte) 0xB6}));

		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());

		assertEquals(0, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());

		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());

		assertEquals(0, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(1, i.readBit());
		assertEquals(0, i.readBit());

	}

}