KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > utils > 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.axis.utils;
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  *
45  * @author <a HREF="mailto:jeremias@apache.org">Jeremias Maerki</a>
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      * @throws IllegalArgumentException if size is negative.
69      */

70     public ByteArrayOutputStream(int size) {
71         if (size < 0) {
72             throw new IllegalArgumentException JavaDoc(
73                     Messages.getMessage("illegalArgumentException01",
74                             Integer.toString(size)));
75         }
76         needNewBuffer(size);
77     }
78
79     private byte[] getBuffer(int index) {
80         return (byte[]) buffers.get(index);
81     }
82
83     private void needNewBuffer(int newcount) {
84         if (currentBufferIndex < buffers.size() - 1) {
85             //Recycling old buffer
86
filledBufferSum += currentBuffer.length;
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(currentBuffer.length << 1,
97                         newcount - filledBufferSum);
98                 filledBufferSum += currentBuffer.length;
99             }
100             currentBufferIndex++;
101             currentBuffer = new byte[newBufferSize];
102             buffers.add(currentBuffer);
103         }
104     }
105
106     /**
107      * @see java.io.OutputStream#write(byte[], int, int)
108      */

109     public synchronized void write(byte[] b, int off, int len) {
110         if ((off < 0)
111                 || (off > b.length)
112                 || (len < 0)
113                 || ((off + len) > b.length)
114                 || ((off + len) < 0)) {
115             throw new IndexOutOfBoundsException JavaDoc(
116                     Messages.getMessage("indexOutOfBoundsException00"));
117         } else if (len == 0) {
118             return;
119         }
120         int newcount = count + len;
121         int remaining = len;
122         int inBufferPos = count - filledBufferSum;
123         while (remaining > 0) {
124             int part = Math.min(remaining, currentBuffer.length - inBufferPos);
125             System.arraycopy(b, off + len - remaining, currentBuffer,
126                     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      *
157      * @throws IOException in case an I/O error occurs
158      */

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

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

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

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

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

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