Repository navigation
Expand file tree
/
Copy pathBitOutputStream.java
More file actions
149 lines (133 loc) · 4.85 KB
/
Copy pathBitOutputStream.java
File metadata and controls
149 lines (133 loc) · 4.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* Write bits-at-a-time where the number of bits is between 1 and 32
* Client programs must call <code>flush</code> or
* <code>close</code> when finished writing or not all bits will be written.
* This class is intended to be used with <code>BitInputStream</code> to
* facilitate reading and writing data in a bits-at-a-time manner.
* <P>
* Updated for version 2.0 to extend java.io.OutputStream
* <P>
* Any exceptions generated are rethrown as <code>RuntimeException</code> objects
* so client code does not have to catch or rethrow them.
* <P>
* @author Owen Astrachan
* @version 1.0, July 2000
* @version 2.0, October 2004
* @version 3.0 April 2022
*/
public class BitOutputStream extends OutputStream {
private OutputStream myOutput;
private int myBuffer;
private int myBitsToGo;
private static final int bmask[] = {
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,
0x7fffff,0xffffff,0x1ffffff,0x3ffffff,0x7ffffff,
0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
};
private static final int BITS_PER_BYTE = 8;
/**
* Required by OutputStream subclasses, write the low
* 8-bits to the underlying outputstream
*/
public void write(int b) throws IOException {
myOutput.write(b);
}
/**
* Create a stream that writes-through to the <code>OutputStream</code> object
* passed as a parameter.
* @param out is the output stream to which bits are written
*/
public BitOutputStream(OutputStream out) {
myOutput = out;
initialize();
}
private void initialize() {
myBuffer = 0;
myBitsToGo = BITS_PER_BYTE;
}
/**
* Construct a bit-at-a-time output stream with specified file
* name.
* @param filename is the name of the file being written
* @throws RuntimeException if opening file fails for either FileNotFound
* or for Security exceptoins
*/
public BitOutputStream(String filename) {
try {
myOutput = new BufferedOutputStream(new FileOutputStream(filename));
} catch (FileNotFoundException fnf) {
throw new RuntimeException("could not create " + filename + " " + fnf);
} catch(SecurityException se) {
throw new RuntimeException("security exception on write " + se);
}
initialize();
}
/**
* Flushes bits not yet written, must be called by client
* programs if <code>close</code> isn't called.
* @throws RuntimeException if there's a problem writing bits
*/
public void flush() {
if (myBitsToGo != BITS_PER_BYTE) {
try {
write( (myBuffer << myBitsToGo) );
} catch (java.io.IOException ioe){
throw new RuntimeException("error writing bits on flush " + ioe);
}
myBuffer = 0;
myBitsToGo = BITS_PER_BYTE;
}
try {
myOutput.flush();
} catch (java.io.IOException ioe){
throw new RuntimeException("error on flush " + ioe);
}
}
/**
* Releases system resources associated with file and
* flushes bits not yet written. Either this function
* or flush must be called or not all bits will be written
* @throws RuntimeException if close fails
*/
public void close() {
flush();
try {
myOutput.close();
} catch (IOException ioe){
throw new RuntimeException("error closing BitOutputStream " + ioe);
}
}
/**
* Write specified number of bits from value to a file.
* @param howManyBits is number of bits to write (1-32)
* @param value is source of bits, rightmost bits are written
* @throws RuntimeException if there's an I/O problem writing bits
*/
public void writeBits(int howManyBits, int value) {
value &= bmask[howManyBits]; // only right most bits valid
while (howManyBits >= myBitsToGo) {
myBuffer = (myBuffer << myBitsToGo) |
(value >> (howManyBits - myBitsToGo));
try {
write(myBuffer);
} catch (java.io.IOException ioe){
throw new RuntimeException("error writing bits " + ioe);
}
value &= bmask[howManyBits - myBitsToGo];
howManyBits -= myBitsToGo;
myBitsToGo = BITS_PER_BYTE;
myBuffer = 0;
}
if (howManyBits > 0) {
myBuffer = (myBuffer << howManyBits) | value;
myBitsToGo -= howManyBits;
}
}
}