-
Notifications
You must be signed in to change notification settings - Fork 107
Expand file tree
/
Copy pathBitInputStream.java
More file actions
101 lines (81 loc) · 2.62 KB
/
Copy pathBitInputStream.java
File metadata and controls
101 lines (81 loc) · 2.62 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
/*
* Reference arithmetic coding
*
* Copyright (c) Project Nayuki
* MIT License. See readme file.
* https://www.nayuki.io/page/reference-arithmetic-coding
*/
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Objects;
/**
* A stream of bits that can be read. Because they come from an underlying byte stream,
* the total number of bits is always a multiple of 8. The bits are read in big endian.
* Mutable and not thread-safe.
* @see BitOutputStream
*/
public final class BitInputStream implements AutoCloseable {
/*---- Fields ----*/
// The underlying byte stream to read from (not null).
private InputStream input;
// Either in the range [0x00, 0xFF] if bits are available, or -1 if end of stream is reached.
private int currentByte;
// Number of remaining bits in the current byte, always between 0 and 7 (inclusive).
private int numBitsRemaining;
/*---- Constructor ----*/
/**
* Constructs a bit input stream based on the specified byte input stream.
* @param in the byte input stream
* @throws NullPointerException if the input stream is {@code null}
*/
public BitInputStream(InputStream in) {
input = Objects.requireNonNull(in);
currentByte = 0;
numBitsRemaining = 0;
}
/*---- Methods ----*/
/**
* Reads a bit from this stream. Returns 0 or 1 if a bit is available, or -1 if
* the end of stream is reached. The end of stream always occurs on a byte boundary.
* @return the next bit of 0 or 1, or -1 for the end of stream
* @throws IOException if an I/O exception occurred
*/
public int read() throws IOException {
if (currentByte == -1)
return -1;
if (numBitsRemaining == 0) {
currentByte = input.read();
if (currentByte == -1)
return -1;
numBitsRemaining = 8;
}
if (numBitsRemaining <= 0)
throw new AssertionError();
numBitsRemaining--;
return (currentByte >>> numBitsRemaining) & 1;
}
/**
* Reads a bit from this stream. Returns 0 or 1 if a bit is available, or throws an {@code EOFException}
* if the end of stream is reached. The end of stream always occurs on a byte boundary.
* @return the next bit of 0 or 1
* @throws IOException if an I/O exception occurred
* @throws EOFException if the end of stream is reached
*/
public int readNoEof() throws IOException {
int result = read();
if (result != -1)
return result;
else
throw new EOFException();
}
/**
* Closes this stream and the underlying input stream.
* @throws IOException if an I/O exception occurred
*/
public void close() throws IOException {
input.close();
currentByte = -1;
numBitsRemaining = 0;
}
}