KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > io > output > ByteArrayOutputStream


1 /*
2  * Copyright 2003,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.commons.io.output;
18  
19 import java.io.IOException JavaDoc;
20 import java.io.OutputStream JavaDoc;
21 import java.io.UnsupportedEncodingException JavaDoc;
22 import java.util.List JavaDoc;
23
24 /**
25  * This class implements an output stream in which the data is
26  * written into a byte array. The buffer automatically grows as data
27  * is written to it.
28  * <p>
29  * The data can be retrieved using <code>toByteArray()</code> and
30  * <code>toString()</code>.
31  * <p>
32  * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
33  * this class can be called after the stream has been closed without
34  * generating an <tt>IOException</tt>.
35  * <p>
36  * This is an alternative implementation of the java.io.ByteArrayOutputStream
37  * class. The original implementation only allocates 32 bytes at the beginning.
38  * As this class is designed for heavy duty it starts at 1024 bytes. In contrast
39  * to the original it doesn't reallocate the whole memory block but allocates
40  * additional buffers. This way no buffers need to be garbage collected and
41  * the contents don't have to be copied to the new buffer. This class is
42  * designed to behave exactly like the original. The only exception is the
43  * deprecated toString(int) method that has been ignored.
44  * @author <a HREF="mailto:jeremias@apache.org">Jeremias Maerki</a>
45  * @version $Id: ByteArrayOutputStream.java,v 1.8 2004/04/24 19:24:09 jeremias Exp $
46  */

47 public class ByteArrayOutputStream extends OutputStream JavaDoc {
48
49     private List JavaDoc buffers = new java.util.ArrayList JavaDoc();
50     private int currentBufferIndex;
51     private int filledBufferSum;
52     private byte[] currentBuffer;
53     private int count;
54
55     /**
56      * Creates a new byte array output stream. The buffer capacity is
57      * initially 1024 bytes, though its size increases if necessary.
58      */

59     public ByteArrayOutputStream() {
60         this(1024);
61     }
62
63     /**
64      * Creates a new byte array output stream, with a buffer capacity of
65      * the specified size, in bytes.
66      *
67      * @param size the initial size.
68      * @exception IllegalArgumentException if size is negative.
69      */

70     public ByteArrayOutputStream(int size) {
71         if (size < 0) {
72             throw new IllegalArgumentException JavaDoc(
73                 "Negative initial size: " + size);
74         }
75         needNewBuffer(size);
76     }
77
78     private byte[] getBuffer(int index) {
79         return (byte[])buffers.get(index);
80     }
81
82     private void needNewBuffer(int newcount) {
83         if (currentBufferIndex < buffers.size() - 1) {
84             //Recycling old buffer
85
filledBufferSum += currentBuffer.length;
86             
87             currentBufferIndex++;
88             currentBuffer = getBuffer(currentBufferIndex);
89         } else {
90             //Creating new buffer
91
int newBufferSize;
92             if (currentBuffer == null) {
93                 newBufferSize = newcount;
94                 filledBufferSum = 0;
95             } else {
96                 newBufferSize = Math.max(
97                     currentBuffer.length << 1,
98                     newcount - filledBufferSum);
99                 filledBufferSum += currentBuffer.length;
100             }
101             
102             currentBufferIndex++;
103             currentBuffer = new byte[newBufferSize];
104             buffers.add(currentBuffer);
105         }
106     }
107
108     /**
109      * @see java.io.OutputStream#write(byte[], int, int)
110      */

111     public synchronized void write(byte[] b, int off, int len) {
112         if ((off < 0)
113                 || (off > b.length)
114                 || (len < 0)
115                 || ((off + len) > b.length)
116                 || ((off + len) < 0)) {
117             throw new IndexOutOfBoundsException JavaDoc();
118         } else if (len == 0) {
119             return;
120         }
121         int newcount = count + len;
122         int remaining = len;
123         int inBufferPos = count - filledBufferSum;
124         while (remaining > 0) {
125             int part = Math.min(remaining, currentBuffer.length - inBufferPos);
126             System.arraycopy(b, off + len - remaining, currentBuffer, inBufferPos, part);
127             remaining -= part;
128             if (remaining > 0) {
129                 needNewBuffer(newcount);
130                 inBufferPos = 0;
131             }
132         }
133         count = newcount;
134     }
135
136     /**
137      * Calls the write(byte[]) method.
138      *
139      * @see java.io.OutputStream#write(int)
140      */

141     public synchronized void write(int b) {
142         write(new byte[] {(byte)b}, 0, 1);
143     }
144
145     /**
146      * @see java.io.ByteArrayOutputStream#size()
147      */

148     public int size() {
149         return count;
150     }
151
152     /**
153      * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in
154      * this class can be called after the stream has been closed without
155      * generating an <tt>IOException</tt>.
156      * @throws IOException in case an I/O error occurs
157      */

158     public void close() throws IOException JavaDoc {
159         //nop
160
}
161
162     /**
163      * @see java.io.ByteArrayOutputStream#reset()
164      */

165     public synchronized void reset() {
166         count = 0;
167         filledBufferSum = 0;
168         currentBufferIndex = 0;
169         currentBuffer = getBuffer(currentBufferIndex);
170     }
171     
172     /**
173      * @see java.io.ByteArrayOutputStream#writeTo(OutputStream)
174      */

175     public synchronized void writeTo(OutputStream JavaDoc out) throws IOException JavaDoc {
176         int remaining = count;
177         for (int i = 0; i < buffers.size(); i++) {
178             byte[] buf = getBuffer(i);
179             int c = Math.min(buf.length, remaining);
180             out.write(buf, 0, c);
181             remaining -= c;
182             if (remaining == 0) {
183                 break;
184             }
185         }
186     }
187
188     /**
189      * @see java.io.ByteArrayOutputStream#toByteArray()
190      */

191     public synchronized byte toByteArray()[] {
192         int remaining = count;
193         int pos = 0;
194         byte newbuf[] = new byte[count];
195         for (int i = 0; i < buffers.size(); i++) {
196             byte[] buf = getBuffer(i);
197             int c = Math.min(buf.length, remaining);
198             System.arraycopy(buf, 0, newbuf, pos, c);
199             pos += c;
200             remaining -= c;
201             if (remaining == 0) {
202                 break;
203             }
204         }
205         return newbuf;
206     }
207
208     /**
209      * @see java.io.ByteArrayOutputStream#toString()
210      */

211     public String JavaDoc toString() {
212         return new String JavaDoc(toByteArray());
213     }
214
215     /**
216      * @see java.io.ByteArrayOutputStream#toString(String)
217      */

218     public String JavaDoc toString(String JavaDoc enc) throws UnsupportedEncodingException JavaDoc {
219         return new String JavaDoc(toByteArray(), enc);
220     }
221
222 }
223
Popular Tags