From 81ba9eb66f8284d8760012973f84cdbe617ceb94 Mon Sep 17 00:00:00 2001 From: pants Date: Mon, 21 Sep 2026 14:16:34 -0700 Subject: init --- p3/BitInputStream.java | 100 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 p3/BitInputStream.java (limited to 'p3/BitInputStream.java') diff --git a/p3/BitInputStream.java b/p3/BitInputStream.java new file mode 100644 index 0000000..e6f02a8 --- /dev/null +++ b/p3/BitInputStream.java @@ -0,0 +1,100 @@ +// The BitOutputStream and BitInputStream classes provide the ability to +// write and read individual bits to a file in a compact form. One major +// limitation of this approach is that the resulting file will always have +// a number of bits that is a multiple of 8. In effect, whatever bits are +// output to the file are padded at the end with 0's to make the total +// number of bits a multiple of 8. +// +// BitInputStream has the following public methods: +// public BitInputStream(String file) +// opens an input stream with the given file name +// public int nextBit() +// reads the next bit from input (throws exception if at end of file) +// public boolean hasNextBit() +// returns true if there's another bit in the input stream to be read +// public void close() +// closes the input + +import java.io.*; +import java.util.*; + +@SuppressWarnings("deprecation") +public class BitInputStream { + private FileInputStream input; + private int currentByte; // current set of bits (buffer) + private int nextByte; // next set of bits (buffer) + private int numBits; // how many bits from buffer have been used + private int remainingAtEnd; // how many bits will be remaining at the end + // after we're done + + private static final int BYTE_SIZE = 8; // bits per byte + + // pre : given file name is legal + // post: creates a BitInputStream reading input from the file + public BitInputStream(String file) { + try { + this.input = new FileInputStream(file); + + // Read in the number of remaining bits at the end + this.remainingAtEnd = this.input.read(); + + // Set up the nextByte field. + this.nextByte = this.input.read(); + } catch (IOException ex) { + throw new RuntimeException(ex.toString()); + } + + this.nextByte(); + } + + public boolean hasNextBit() { + boolean atEnd = this.currentByte == -1; + boolean onlyRemaining = this.nextByte == -1 + && BYTE_SIZE - this.numBits == this.remainingAtEnd; + return !atEnd && !onlyRemaining; + } + + // post: reads next bit from input + // throws NoSuchElementException if there is no bit to return + public int nextBit() { + // if at eof, throw exception + if (!this.hasNextBit()) { + throw new NoSuchElementException(); + } + int result = this.currentByte % 2; + this.currentByte /= 2; + this.numBits++; + if (this.numBits == BYTE_SIZE) { + this.nextByte(); + } + return result; + } + + // post: refreshes the internal buffer with the next BYTE_SIZE bits + private void nextByte() { + this.currentByte = this.nextByte; + if (this.currentByte != -1) { + try { + this.nextByte = this.input.read(); + } catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + + this.numBits = 0; + } + + // post: input is closed + public void close() { + try { + this.input.close(); + } catch (IOException e) { + throw new RuntimeException(e.toString()); + } + } + + // included to ensure that the stream is closed + protected void finalize() { + this.close(); + } +} -- cgit v1.2.3