Source code: com/arranger/jarl/io/CompressedOutputStream.java
1 package com.arranger.jarl.io;
2
3
4 import java.io.IOException;
5 import java.io.OutputStream;
6
7 /**
8 * Essentially, CompressedOutputStream is much like DeflaterOutputStream with
9 * these differences:
10 * 1) CompressedOutputStream "finishes" the compressed output every time
11 * a 'flush' operation is performed. The stream remains open, however. After
12 * a flush, the compression is reset. This allows one to call flush() and
13 * have the stream truly flush all compressed data. flush() may be called
14 * as often as necessary. Note, that since flush() restarts the compression,
15 * it is much more effecient to call flush as few times as possible (in other
16 * words, send as much data as possible before calling flush). In most cases,
17 * the output stream need not be flushed until you need to wait for a response
18 * from your peer on the data you have sent thus far. Of course, the stream
19 * is automatically flushed when closed.
20 * 2) The write(int) method has been slightly optimized over the
21 * DeflaterOutputStream version (DeflaterOutputStream would create a new
22 * one byte buffer every time write was called. CompressedOutputStream
23 * reuses an instance buffer. This means, of course, that
24 * CompressedOutputStream in not inherently thread safe)
25 * 3) Simple statistics are kept for the stream: number of uncompressed bytes
26 * written (this would be the number of bytes sent to the write() methods)
27 * and the number of actual compressed output bytes.
28 */
29 public class CompressedOutputStream extends GZipOutputStreamEx {
30
31 protected static final int COMPRESSION_LEVEL_DEFAULT = 9;
32
33 /**
34 * This is compression level used for DeflatedCompressionStream
35 * Default value is 3 (possible values are 0 to 9
36 */
37 protected static int compressionLevel = COMPRESSION_LEVEL_DEFAULT;
38
39 /**
40 * Obtain compression level
41 */
42 protected static int getCompressionLevel() {
43 return compressionLevel;
44 }
45
46 protected long _compOut = 0;
47 protected long _totalOut = 0;
48 private byte _b[] = new byte[1];
49
50 public CompressedOutputStream(OutputStream out) throws IOException {
51 super(out, getCompressionLevel());
52 }
53
54 public CompressedOutputStream(OutputStream out, int compression) throws IOException {
55 super(out, compression);
56 }
57
58 public void write(int b) throws IOException {
59 _b[0] = (byte)(b & 0xff);
60 write(_b, 0, 1);
61 }
62
63 public void write(byte[] b, int off, int len) throws IOException {
64 long compBegin = def.getTotalOut();
65 long begin = def.getTotalIn();
66 super.write(b, off, len);
67 _compOut += def.getTotalOut() - compBegin;
68 _totalOut += def.getTotalIn() - begin;
69 }
70
71 public void flush() throws IOException {
72 super.flush();
73 finish();
74 def.reset();
75 }
76
77 public void finish() throws IOException {
78 long compBegin = def.getTotalOut();
79 long begin = def.getTotalIn();
80 super.finish();
81 _compOut += def.getTotalOut() - compBegin;
82 _totalOut += def.getTotalIn() - begin;
83 }
84
85 public long getCompressedTotalOut() {
86 return _compOut;
87 }
88
89 public long getUncompressedTotalOut() {
90 return _totalOut;
91 }
92
93 public void close() throws IOException {
94 finish();
95 def.end(); /* end the deflator to fix a memory leak */
96 out.close();
97 }
98 }