View Javadoc

1   /*
2    * Trip Tracker, a real-time position tracking system for the Internet.
3    * Copyright (C) 2006  Team Trip Tracker
4    *
5    * This program is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License as published by the
7    * Free Software Foundation; either version 2 of the License, or (at your
8    * option) any later version.
9    *
10   * This program is distributed in the hope that it will be useful, but
11   * WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13   * General Public License for more details.
14   *
15   * You should have received a copy of the GNU General Public License along
16   * with this program; if not, write to the Free Software Foundation, Inc.,
17   * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
18   */
19  
20  package triptracker.testing.compress;
21  
22  /***
23   * Output stream that compresses data. A compressed block 
24   * is generated and transmitted once a given number of bytes 
25   * have been written, or when the flush method is invoked.
26   * 
27   * Copyright 2005 - Philip Isenhour - http://javatechniques.com/
28   * 
29   * This software is provided 'as-is', without any express or 
30   * implied warranty. In no event will the authors be held liable 
31   * for any damages arising from the use of this software.
32   *
33   * Permission is granted to anyone to use this software for any 
34   * purpose, including commercial applications, and to alter it and 
35   * redistribute it freely, subject to the following restrictions:
36   *
37   *  1. The origin of this software must not be misrepresented; you 
38   *     must not claim that you wrote the original software. If you 
39   *     use this software in a product, an acknowledgment in the 
40   *     product documentation would be appreciated but is not required.
41   *
42   *  2. Altered source versions must be plainly marked as such, and 
43   *     must not be misrepresented as being the original software.
44   *
45   *  3. This notice may not be removed or altered from any source 
46   *     distribution.
47   *
48   * $Id:  1.1 2005/10/26 17:19:05 isenhour Exp $
49   */
50  import java.io.FilterOutputStream;
51  import java.io.IOException;
52  import java.io.OutputStream;
53  import java.util.zip.Deflater;
54  
55  public class CompressedBlockOutputStream extends FilterOutputStream {
56  	/***
57  	 * Buffer for input data
58  	 */
59  	private byte[] inBuf = null;
60  
61  	/***
62  	 * Buffer for compressed data to be written
63  	 */
64  	private byte[] outBuf = null;
65  
66  	/***
67  	 * Number of bytes in the buffer
68  	 */
69  	private int len = 0;
70  
71  	/***
72  	 * Deflater for compressing data
73  	 */
74  	private Deflater deflater = null;
75  
76  	/***
77  	 * Constructs a CompressedBlockOutputStream that writes to the given
78  	 * underlying output stream 'os' and sends a compressed block once 'size'
79  	 * byte have been written. The default compression strategy and level are
80  	 * used.
81  	 */
82  	public CompressedBlockOutputStream(OutputStream os, int size)
83  			throws IOException {
84  		this(os, size, Deflater.DEFAULT_COMPRESSION, Deflater.DEFAULT_STRATEGY);
85  	}
86  
87  	/***
88  	 * Constructs a CompressedBlockOutputStream that writes to the given
89  	 * underlying output stream 'os' and sends a compressed block once 'size'
90  	 * byte have been written. The compression level and strategy should be
91  	 * specified using the constants defined in java.util.zip.Deflator.
92  	 */
93  	public CompressedBlockOutputStream(OutputStream os, int size, int level,
94  			int strategy) throws IOException {
95  		super(os);
96  		this.inBuf = new byte[size];
97  		this.outBuf = new byte[size + 64];
98  		this.deflater = new Deflater(level);
99  		this.deflater.setStrategy(strategy);
100 	}
101 
102 	protected void compressAndSend() throws IOException {
103 		if (len > 0) {
104 			deflater.setInput(inBuf, 0, len);
105 			deflater.finish();
106 			int size = deflater.deflate(outBuf);
107 
108 			// Write the size of the compressed data, followed
109 			// by the size of the uncompressed data
110 			out.write((size >> 24) & 0xFF);
111 			out.write((size >> 16) & 0xFF);
112 			out.write((size >> 8) & 0xFF);
113 			out.write((size >> 0) & 0xFF);
114 
115 			out.write((len >> 24) & 0xFF);
116 			out.write((len >> 16) & 0xFF);
117 			out.write((len >> 8) & 0xFF);
118 			out.write((len >> 0) & 0xFF);
119 
120 			out.write(outBuf, 0, size);
121 			out.flush();
122 
123 			len = 0;
124 			deflater.reset();
125 		}
126 	}
127 
128 	@Override
129 	public void write(int b) throws IOException {
130 		inBuf[len++] = (byte) b;
131 		if (len == inBuf.length) {
132 			compressAndSend();
133 		}
134 	}
135 
136 	@Override
137 	public void write(byte[] b, int boff, int blen) throws IOException {
138 		while ((len + blen) > inBuf.length) {
139 			int toCopy = inBuf.length - len;
140 			System.arraycopy(b, boff, inBuf, len, toCopy);
141 			len += toCopy;
142 			compressAndSend();
143 			boff += toCopy;
144 			blen -= toCopy;
145 		}
146 		System.arraycopy(b, boff, inBuf, len, blen);
147 		len += blen;
148 	}
149 
150 	@Override
151 	public void flush() throws IOException {
152 		compressAndSend();
153 		out.flush();
154 	}
155 
156 	@Override
157 	public void close() throws IOException {
158 		compressAndSend();
159 		out.close();
160 	}
161 }