1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package triptracker.testing.compress;
21
22 /***
23 * Input stream that decompresses data.
24 *
25 * Copyright 2005 - Philip Isenhour - http://javatechniques.com/
26 *
27 * This software is provided 'as-is', without any express or
28 * implied warranty. In no event will the authors be held liable
29 * for any damages arising from the use of this software.
30 *
31 * Permission is granted to anyone to use this software for any
32 * purpose, including commercial applications, and to alter it and
33 * redistribute it freely, subject to the following restrictions:
34 *
35 * 1. The origin of this software must not be misrepresented; you
36 * must not claim that you wrote the original software. If you
37 * use this software in a product, an acknowledgment in the
38 * product documentation would be appreciated but is not required.
39 *
40 * 2. Altered source versions must be plainly marked as such, and
41 * must not be misrepresented as being the original software.
42 *
43 * 3. This notice may not be removed or altered from any source
44 * distribution.
45 *
46 * $Id: 1.2 2005/10/26 17:40:19 isenhour Exp $
47 */
48 import java.io.EOFException;
49 import java.io.FilterInputStream;
50 import java.io.IOException;
51 import java.io.InputStream;
52 import java.util.zip.DataFormatException;
53 import java.util.zip.Inflater;
54
55 public class CompressedBlockInputStream extends FilterInputStream {
56 /***
57 * Buffer of compressed data read from the stream
58 */
59 private byte[] inBuf = null;
60
61 /***
62 * Length of data in the input data
63 */
64 private int inLength = 0;
65
66 /***
67 * Buffer of uncompressed data
68 */
69 private byte[] outBuf = null;
70
71 /***
72 * Offset and length of uncompressed data
73 */
74 private int outOffs = 0;
75
76 private int outLength = 0;
77
78 /***
79 * Inflater for decompressing
80 */
81 private Inflater inflater = null;
82
83 public CompressedBlockInputStream(InputStream is) throws IOException {
84 super(is);
85 inflater = new Inflater();
86 }
87
88 private void readAndDecompress() throws IOException {
89
90 int ch1 = in.read();
91 int ch2 = in.read();
92 int ch3 = in.read();
93 int ch4 = in.read();
94 if ((ch1 | ch2 | ch3 | ch4) < 0)
95 throw new EOFException();
96 inLength = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
97
98 ch1 = in.read();
99 ch2 = in.read();
100 ch3 = in.read();
101 ch4 = in.read();
102 if ((ch1 | ch2 | ch3 | ch4) < 0)
103 throw new EOFException();
104 outLength = ((ch1 << 24) + (ch2 << 16) + (ch3 << 8) + (ch4 << 0));
105
106
107 if ((inBuf == null) || (inLength > inBuf.length)) {
108 inBuf = new byte[inLength];
109 }
110
111 if ((outBuf == null) || (outLength > outBuf.length)) {
112 outBuf = new byte[outLength];
113 }
114
115
116
117
118
119 int inOffs = 0;
120 while (inOffs < inLength) {
121 int inCount = in.read(inBuf, inOffs, inLength - inOffs);
122 if (inCount == -1) {
123 throw new EOFException();
124 }
125 inOffs += inCount;
126 }
127
128 inflater.setInput(inBuf, 0, inLength);
129 try {
130 inflater.inflate(outBuf);
131 } catch (DataFormatException dfe) {
132 throw new IOException("Data format exception - "
133 + dfe.getMessage());
134 }
135
136
137
138 inflater.reset();
139
140 outOffs = 0;
141 }
142
143 @Override
144 public int read() throws IOException {
145 if (outOffs >= outLength) {
146 try {
147 readAndDecompress();
148 } catch (EOFException eof) {
149 return -1;
150 }
151 }
152
153 return outBuf[outOffs++] & 0xff;
154 }
155
156
157
158
159
160
161 @Override
162 public int read(byte[] b, int off, int len) throws IOException {
163 int count = 0;
164 while (count < len) {
165 if (outOffs >= outLength) {
166 try {
167
168
169
170 if ((count > 0) && (in.available() == 0))
171 return count;
172 else
173 readAndDecompress();
174 } catch (EOFException eof) {
175 if (count == 0)
176 count = -1;
177 return count;
178 }
179 }
180
181 int toCopy = Math.min(outLength - outOffs, len - count);
182 System.arraycopy(outBuf, outOffs, b, off + count, toCopy);
183 outOffs += toCopy;
184 count += toCopy;
185 }
186
187 return count;
188 }
189
190 @Override
191 public int available() throws IOException {
192
193
194 return (outLength - outOffs) + in.available();
195 }
196
197 }