KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > jodd > io > FastByteArrayOutputStream


1 // Copyright (c) 2003-2007, Jodd Team (jodd.sf.net). All Rights Reserved.
2

3 package jodd.io;
4
5 import java.io.IOException JavaDoc;
6 import java.io.OutputStream JavaDoc;
7 import java.io.UnsupportedEncodingException JavaDoc;
8 import java.util.List JavaDoc;
9
10 /**
11  * This class implements an output stream in which the data is
12  * written into a byte array. The buffer automatically grows as data
13  * is written to it.
14  * <p>
15  * The data can be retrieved using <code>toByteArray()</code> and
16  * <code>toString()</code>.
17  * <p>
18  * Closing a <code>FastByteArrayOutputStream</code> has no effect. The methods in
19  * this class can be called after the stream has been closed without
20  * generating an <code>IOException</code>.
21  * <p>
22  * This is an alternative implementation of the java.io.FastByteArrayOutputStream
23  * class. The original implementation only allocates 32 bytes at the beginning.
24  * As this class is designed for heavy duty it starts at 1024 bytes. In contrast
25  * to the original it doesn't reallocate the whole memory block but allocates
26  * additional buffers. This way no buffers need to be garbage collected and
27  * the contents don't have to be copied to the new buffer. This class is
28  * designed to behave exactly like the original. The only exception is the
29  * deprecated toString(int) method that has been ignored.
30  *
31  * @author <a HREF="mailto:jeremias@apache.org">Jeremias Maerki</a>
32  */

33 public class FastByteArrayOutputStream extends OutputStream JavaDoc {
34
35     private List JavaDoc buffers = new java.util.ArrayList JavaDoc();
36     private int currentBufferIndex;
37     private int filledBufferSum;
38     private byte[] currentBuffer;
39     private int count;
40
41     /**
42      * Creates a new byte array output stream. The buffer capacity is
43      * initially 1024 bytes, though its size increases if necessary.
44      */

45     public FastByteArrayOutputStream() {
46         this(1024);
47     }
48
49     /**
50      * Creates a new byte array output stream, with a buffer capacity of
51      * the specified size, in bytes.
52      *
53      * @param size the initial size.
54      * @throws IllegalArgumentException if size is negative.
55      */

56     public FastByteArrayOutputStream(int size) {
57         if (size < 0) {
58             throw new IllegalArgumentException JavaDoc("Negative initial size: " + size);
59         }
60         needNewBuffer(size);
61     }
62
63     private byte[] getBuffer(int index) {
64         return (byte[]) buffers.get(index);
65     }
66
67     private void needNewBuffer(int newcount) {
68         if (currentBufferIndex < buffers.size() - 1) {
69             //Recycling old buffer
70
filledBufferSum += currentBuffer.length;
71
72             currentBufferIndex++;
73             currentBuffer = getBuffer(currentBufferIndex);
74         } else {
75             //Creating new buffer
76
int newBufferSize;
77             if (currentBuffer == null) {
78                 newBufferSize = newcount;
79                 filledBufferSum = 0;
80             } else {
81                 newBufferSize = Math.max(
82                         currentBuffer.length << 1,
83                         newcount - filledBufferSum);
84                 filledBufferSum += currentBuffer.length;
85             }
86
87             currentBufferIndex++;
88             currentBuffer = new byte[newBufferSize];
89             buffers.add(currentBuffer);
90         }
91     }
92
93     /**
94      * @see java.io.OutputStream#write(byte[], int, int)
95      */

96     public synchronized void write(byte[] b, int off, int len) {
97         if ((off < 0)
98                 || (off > b.length)
99                 || (len < 0)
100                 || ((off + len) > b.length)
101                 || ((off + len) < 0)) {
102             throw new IndexOutOfBoundsException JavaDoc();
103         } else if (len == 0) {
104             return;
105         }
106         int newcount = count + len;
107         int remaining = len;
108         int inBufferPos = count - filledBufferSum;
109         while (remaining > 0) {
110             int part = Math.min(remaining, currentBuffer.length - inBufferPos);
111             System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
112             remaining -= part;
113             if (remaining > 0) {
114                 needNewBuffer(newcount);
115                 inBufferPos = 0;
116             }
117         }
118         count = newcount;
119     }
120
121     /**
122      * Calls the write(byte[]) method.
123      *
124      * @see java.io.OutputStream#write(int)
125      */

126     public synchronized void write(int b) {
127         write(new byte[]{(byte) b}, 0, 1);
128     }
129
130     /**
131      * @see java.io.ByteArrayOutputStream#size()
132      */

133     public int size() {
134         return count;
135     }
136
137     /**
138      * Closing a <code>FastByteArrayOutputStream</code> has no effect. The methods in
139      * this class can be called after the stream has been closed without
140      * generating an <code>IOException</code>.
141      */

142     public void close() {
143         //nop
144
}
145
146     /**
147      * @see java.io.ByteArrayOutputStream#reset()
148      */

149     public synchronized void reset() {
150         count = 0;
151         filledBufferSum = 0;
152         currentBufferIndex = 0;
153         currentBuffer = getBuffer(currentBufferIndex);
154     }
155
156     /**
157      * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
158      */

159     public synchronized void writeTo(OutputStream JavaDoc out) throws IOException JavaDoc {
160         int remaining = count;
161         for (int i = 0; i < buffers.size(); i++) {
162             byte[] buf = getBuffer(i);
163             int c = Math.min(buf.length, remaining);
164             out.write(buf, 0, c);
165             remaining -= c;
166             if (remaining == 0) {
167                 break;
168             }
169         }
170     }
171
172     /**
173      * @see java.io.ByteArrayOutputStream#toByteArray()
174      */

175     public synchronized byte toByteArray()[] {
176         int remaining = count;
177         int pos = 0;
178         byte newbuf[] = new byte[count];
179         for (int i = 0; i < buffers.size(); i++) {
180             byte[] buf = getBuffer(i);
181             int c = Math.min(buf.length, remaining);
182             System.arraycopy(buf, 0, newbuf, pos, c);
183             pos += c;
184             remaining -= c;
185             if (remaining == 0) {
186                 break;
187             }
188         }
189         return newbuf;
190     }
191
192     /**
193      * @see java.io.ByteArrayOutputStream#toString()
194      */

195     public String JavaDoc toString() {
196         return new String JavaDoc(toByteArray());
197     }
198
199     /**
200      * @see java.io.ByteArrayOutputStream#toString(String)
201      */

202     public String JavaDoc toString(String JavaDoc enc) throws UnsupportedEncodingException JavaDoc {
203         return new String JavaDoc(toByteArray(), enc);
204     }
205
206 }
207
Popular Tags