KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > iapi > services > io > DynamicByteArrayOutputStream


1 /*
2
3    Derby - Class org.apache.derby.iapi.services.io.DynamicByteArrayOutputStream
4
5    Licensed to the Apache Software Foundation (ASF) under one or more
6    contributor license agreements. See the NOTICE file distributed with
7    this work for additional information regarding copyright ownership.
8    The ASF licenses this file to you under the Apache License, Version 2.0
9    (the "License"); you may not use this file except in compliance with
10    the License. You may obtain a copy of the License at
11
12       http://www.apache.org/licenses/LICENSE-2.0
13
14    Unless required by applicable law or agreed to in writing, software
15    distributed under the License is distributed on an "AS IS" BASIS,
16    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17    See the License for the specific language governing permissions and
18    limitations under the License.
19
20  */

21
22 package org.apache.derby.iapi.services.io;
23
24 import org.apache.derby.iapi.services.sanity.SanityManager;
25
26 import java.io.InputStream JavaDoc;
27 import java.io.IOException JavaDoc;
28 import java.io.OutputStream JavaDoc;
29
30 /**
31     A DynamicByteArrayOutputStream allows writing to a dynamically resizable
32     array of bytes. In addition to dynamic resizing, this extension allows
33     the user of this class to have more control over the position of the stream
34     and can get a direct reference of the array.
35 */

36 public class DynamicByteArrayOutputStream extends OutputStream JavaDoc {
37
38     private static int INITIAL_SIZE = 4096;
39
40     private byte[] buf;
41     private int position;
42     private int used; // how many bytes are used
43
private int beginPosition;
44
45     public DynamicByteArrayOutputStream() {
46         this(INITIAL_SIZE);
47     }
48
49     public DynamicByteArrayOutputStream(int size) {
50         super();
51
52         buf = new byte[size];
53     }
54
55     public DynamicByteArrayOutputStream(byte[] data) {
56         super();
57
58         buf = data;
59     }
60
61     public DynamicByteArrayOutputStream(DynamicByteArrayOutputStream toBeCloned) {
62
63         byte[] cbuf = toBeCloned.getByteArray();
64         buf = new byte[cbuf.length];
65
66         write(cbuf, 0, cbuf.length);
67         position = toBeCloned.getPosition();
68         used = toBeCloned.getUsed();
69         beginPosition = toBeCloned.getBeginPosition();
70     }
71
72     /*
73      * OutputStream methods
74      */

75     public void write(int b)
76     {
77         if (position >= buf.length)
78             expandBuffer(INITIAL_SIZE);
79
80         buf[position++] = (byte) b;
81
82         if (position > used)
83             used = position;
84     }
85     
86     public void write(byte[] b, int off, int len)
87     {
88         if ((position+len) > buf.length)
89             expandBuffer(len);
90
91         System.arraycopy(b, off, buf, position, len);
92         position += len;
93
94         if (position > used)
95             used = position;
96     }
97
98     void writeCompleteStream(InputStream JavaDoc dataIn, int len) throws IOException JavaDoc
99     {
100         if ((position+len) > buf.length)
101             expandBuffer(len);
102
103         org.apache.derby.iapi.services.io.InputStreamUtil.readFully(dataIn, buf, position, len);
104         position += len;
105
106         if (position > used)
107             used = position;
108     }
109
110     public void close()
111     {
112         buf = null;
113         reset();
114     }
115
116     /*
117      * Specific methods
118      */

119
120     /**
121         Reset the stream for reuse
122     */

123     public void reset()
124     {
125         position = 0;
126         beginPosition = 0;
127         used = 0;
128     }
129
130     /**
131         Get a reference to the byte array stored in the byte array output
132         stream. Note that the byte array may be longer that getPosition().
133         Bytes beyond and including the current poistion are invalid.
134     */

135     public byte[] getByteArray()
136     {
137         return buf;
138     }
139
140     /**
141         Get the number of bytes that was used.
142     */

143     public int getUsed()
144     {
145         return used;
146     }
147
148     /**
149         Get the current position in the stream
150     */

151     public int getPosition()
152     {
153         return position;
154     }
155
156     /**
157         Get the current position in the stream
158     */

159     public int getBeginPosition()
160     {
161         return beginPosition;
162     }
163
164     /**
165         Set the position of the stream pointer.
166         It is up to the caller to make sure the stream has no gap of garbage in
167         it or useful information is not left out at the end because the stream
168         does not remember anything about the previous position.
169     */

170     public void setPosition(int newPosition)
171     {
172         if (newPosition > position)
173         {
174             if (newPosition > buf.length)
175                 expandBuffer(newPosition - buf.length);
176         }
177
178         position = newPosition;
179
180         if (position > used)
181             used = position;
182
183         return ;
184     }
185
186     /**
187         Set the begin position of the stream pointer.
188         If the newBeginPosition is larger than the stream itself,
189         then, the begin position is not set.
190     */

191     public void setBeginPosition(int newBeginPosition)
192     {
193
194         if (newBeginPosition > buf.length)
195             return;
196
197         beginPosition = newBeginPosition;
198     }
199
200     /**
201         Shrink the buffer left by the amount given. Ie.
202         bytes from 0 to amountToShrinkBy are thrown away
203     */

204     public void discardLeft(int amountToShrinkBy) {
205
206         System.arraycopy(buf, amountToShrinkBy, buf, 0,
207             used - amountToShrinkBy);
208
209         position -= amountToShrinkBy;
210         used -= amountToShrinkBy;
211     }
212
213     /**
214         Expand the buffer by at least the number of bytes requested in minExtension.
215
216         To optimize performance and reduce memory copies and allocation, we have a staged buffer
217         expansion.
218
219         <UL>
220         <LI> buf.length < 128k - increase by 4k
221         <LI> buf.length < 1Mb - increase by 128k
222         <LI> otherwise increase by 1Mb.
223         </UL>
224
225         In all cases, if minExpansion is greater than the value about then the buffer will
226         be increased by minExtension.
227     */

228     private void expandBuffer(int minExtension)
229     {
230         if (buf.length < (128 * 1024)) {
231             if (minExtension < INITIAL_SIZE)
232                 minExtension = INITIAL_SIZE;
233         } else if (buf.length < (1024 * 1024)) {
234
235             if (minExtension < (128 * 1024))
236                 minExtension = (128 * 1024);
237         } else {
238             if (minExtension < (1024 * 1024))
239                 minExtension = 1024 * 1024;
240         }
241
242         int newsize = buf.length + minExtension;
243
244         byte[] newbuf = new byte[newsize];
245         System.arraycopy(buf, 0, newbuf, 0, buf.length);
246         buf = newbuf;
247     }
248
249 }
250
Popular Tags