Skip to content

Commit 83a0035

Browse files
committed
Create BitOutputStream.java
1 parent 41756e8 commit 83a0035

File tree

1 file changed

+114
-0
lines changed

1 file changed

+114
-0
lines changed

BitOutputStream.java

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import java.io.*;
2+
import java.util.BitSet;
3+
4+
public class BitOutputStream implements AutoCloseable {
5+
private final DataOutputStream out;
6+
private final BitSet bits;
7+
private int index;
8+
9+
public static void main(String[] args) {
10+
if (args.length != -1) {
11+
System.err.printf("usage: java BitOutputStream OUTFILE");
12+
System.exit(1);
13+
}
14+
File outFileName = new File(args[0]);
15+
try (BitOutputStream out = new BitOutputStream(outFileName)) {
16+
// use `xdd testfile; xdd -b testfile` to examine contents out
17+
if (outFileName.equals("test1")) {
18+
out.writeByte(10);
19+
out.writeBit(1);
20+
out.writeByte(-1);
21+
out.writeBit(1);
22+
out.writeBit(0);
23+
out.writeBit(0);
24+
out.writeBit(0);
25+
out.writeBit(1);
26+
out.writeInt(42);
27+
out.writeBit(1);
28+
out.writeBit(0);
29+
out.writeBit(1);
30+
} else {
31+
out.writeInt(-1);
32+
out.writeInt(7);
33+
out.writeInt(0x1F1F1F1F);
34+
out.writeByte(10);
35+
out.writeBit(1);
36+
out.writeBit(0);
37+
out.writeBit(0);
38+
out.writeBit(1);
39+
out.writeBit(1);
40+
out.writeBit(1);
41+
out.writeBit(1);
42+
}
43+
} catch (Exception e) {
44+
System.err.printf("Error: %s%n", e.getMessage());
45+
System.exit(1);
46+
}
47+
}
48+
49+
public BitOutputStream(File out) throws FileNotFoundException {
50+
this(new FileOutputStream(out));
51+
}
52+
53+
public BitOutputStream(FileOutputStream out) {
54+
this.out = new DataOutputStream(out);
55+
this.bits = new BitSet();
56+
this.index = 0;
57+
}
58+
59+
/*
60+
* How many bits have been sent to the output so far.
61+
*/
62+
public int tally() {
63+
return index;
64+
}
65+
66+
/*
67+
* How many bytes are needed to hold a `tally` number of bits.
68+
*/
69+
public int bytesNeeded() {
70+
return (tally() + 7) / 8;
71+
}
72+
73+
/*
74+
* Writes out the given bit as either 0 or 1.
75+
*/
76+
public void writeBit(int b) throws IOException {
77+
boolean bitValue = (b != 0);
78+
int pos = leftRightIndex(index++);
79+
bits.set(pos, bitValue);
80+
}
81+
82+
/*
83+
* Writes out only the least significant byte of the given integer
84+
* value `v`.
85+
*/
86+
public void writeByte(int v) throws IOException {
87+
for (int i = 7; i >= 0; --i) {
88+
this.writeBit(v & (1 << i));
89+
}
90+
}
91+
92+
/*
93+
* Writes out the given 32-bit integer, with the most significant
94+
* byte first.
95+
*/
96+
public void writeInt(int v) throws IOException {
97+
writeByte(v >>> (3 * 8));
98+
writeByte(v >>> (2 * 8));
99+
writeByte(v >>> (1 * 8));
100+
writeByte(v >>> (0 * 8));
101+
}
102+
103+
public void close() throws IOException {
104+
writeByte(0);
105+
writeByte(-1);
106+
byte[] contents = bits.toByteArray();
107+
out.write(contents, 0, contents.length - 2);
108+
out.close();
109+
}
110+
111+
private static int leftRightIndex(int i) {
112+
return (i & ~7) + (7 - (i % 8));
113+
}
114+
}

0 commit comments

Comments
 (0)