summaryrefslogtreecommitdiff
path: root/p3/BitOutputStream.java
diff options
context:
space:
mode:
Diffstat (limited to 'p3/BitOutputStream.java')
-rw-r--r--p3/BitOutputStream.java74
1 files changed, 74 insertions, 0 deletions
diff --git a/p3/BitOutputStream.java b/p3/BitOutputStream.java
new file mode 100644
index 0000000..4c60a68
--- /dev/null
+++ b/p3/BitOutputStream.java
@@ -0,0 +1,74 @@
+// 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.
+
+import java.io.*;
+import java.util.*;
+
+@SuppressWarnings("deprecation")
+public class BitOutputStream {
+ private PrintStream output;
+ private List<Integer> buffer;
+ private int currentByte; // a buffer used to build up next set of digits
+ private int numBits; // how many digits are currently in the buffer
+ private boolean debug; // set to true to write ASCII 0s and 1s rather than
+ // bits
+
+ private static final int BYTE_SIZE = 8; // digits per byte
+
+ // Creates a BitOutputStream sending output to the given stream. If debug
+ // is set to true, bits are printed as ASCII 0s and 1s.
+ public BitOutputStream(PrintStream output, boolean debug) {
+ this.buffer = new ArrayList<Integer>();
+ this.output = output;
+ this.debug = debug;
+ }
+
+ // Writes given bit to output
+ public void write(int bit) {
+ if (this.debug) {
+ System.out.print(bit);
+ }
+ if (bit < 0 || bit > 1) {
+ throw new IllegalArgumentException("Illegal bit: " + bit);
+ }
+ this.currentByte += bit << this.numBits;
+ this.numBits++;
+ if (this.numBits == BYTE_SIZE) {
+ this.buffer.add(this.currentByte);
+ this.numBits = 0;
+ this.currentByte = 0;
+ }
+ }
+
+ // post: output is closed
+ public void close() {
+ int remaining = BYTE_SIZE - this.numBits;
+
+ if (remaining == 8) {
+ remaining = 0;
+ }
+
+ /* Flush the last byte (if there is one) */
+ if (remaining > 0) {
+ this.buffer.add(this.currentByte);
+ }
+
+ /* Now that we've received all the output, prepend it with the number
+ * of missing bits from the end.
+ */
+ this.output.write(remaining);
+ for (int b : this.buffer) {
+ this.output.write(b);
+ }
+ this.output.close();
+ }
+
+ // included to ensure that the stream is closed
+ protected void finalize() {
+ this.close();
+ }
+}