ByteArrayOutputStream.java revision f33eae7e84eb6d3b0f4e86b59605bb3de73009f3
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package java.io; 19 20import org.apache.harmony.luni.util.Msg; 21 22/** 23 * A specialized {@link OutputStream} for class for writing content to an 24 * (internal) byte array. As bytes are written to this stream, the byte array 25 * may be expanded to hold more bytes. When the writing is considered to be 26 * finished, a copy of the byte array can be requested from the class. 27 * 28 * @see ByteArrayInputStream 29 */ 30public class ByteArrayOutputStream extends OutputStream { 31 /** 32 * The byte array containing the bytes written. 33 */ 34 protected byte[] buf; 35 36 /** 37 * The number of bytes written. 38 */ 39 protected int count; 40 41 /** 42 * Constructs a new ByteArrayOutputStream with a default size of 32 bytes. 43 * If more than 32 bytes are written to this instance, the underlying byte 44 * array will expand. 45 */ 46 public ByteArrayOutputStream() { 47 super(); 48 buf = new byte[32]; 49 } 50 51 /** 52 * Constructs a new {@code ByteArrayOutputStream} with a default size of 53 * {@code size} bytes. If more than {@code size} bytes are written to this 54 * instance, the underlying byte array will expand. 55 * 56 * @param size 57 * initial size for the underlying byte array, must be 58 * non-negative. 59 * @throws IllegalArgumentException 60 * if {@code size} < 0. 61 */ 62 public ByteArrayOutputStream(int size) { 63 super(); 64 if (size >= 0) { 65 buf = new byte[size]; 66 } else { 67 throw new IllegalArgumentException(Msg.getString("K005e")); 68 } 69 } 70 71 /** 72 * Closes this stream. This releases system resources used for this stream. 73 * 74 * @throws IOException 75 * if an error occurs while attempting to close this stream. 76 */ 77 @Override 78 public void close() throws IOException { 79 /** 80 * Although the spec claims "A closed stream cannot perform output 81 * operations and cannot be reopened.", this implementation must do 82 * nothing. 83 */ 84 super.close(); 85 } 86 87 private void expand(int i) { 88 /* Can the buffer handle @i more bytes, if not expand it */ 89 if (count + i <= buf.length) { 90 return; 91 } 92 93 byte[] newbuf = new byte[(count + i) * 2]; 94 System.arraycopy(buf, 0, newbuf, 0, count); 95 buf = newbuf; 96 } 97 98 /** 99 * Resets this stream to the beginning of the underlying byte array. All 100 * subsequent writes will overwrite any bytes previously stored in this 101 * stream. 102 */ 103 public synchronized void reset() { 104 count = 0; 105 } 106 107 /** 108 * Returns the total number of bytes written to this stream so far. 109 * 110 * @return the number of bytes written to this stream. 111 */ 112 public int size() { 113 return count; 114 } 115 116 /** 117 * Returns the contents of this ByteArrayOutputStream as a byte array. Any 118 * changes made to the receiver after returning will not be reflected in the 119 * byte array returned to the caller. 120 * 121 * @return this stream's current contents as a byte array. 122 */ 123 public synchronized byte[] toByteArray() { 124 byte[] newArray = new byte[count]; 125 System.arraycopy(buf, 0, newArray, 0, count); 126 return newArray; 127 } 128 129 /** 130 * Returns the contents of this ByteArrayOutputStream as a string. Any 131 * changes made to the receiver after returning will not be reflected in the 132 * string returned to the caller. 133 * 134 * @return this stream's current contents as a string. 135 */ 136 137 @Override 138 public String toString() { 139 return new String(buf, 0, count); 140 } 141 142 /** 143 * Returns the contents of this ByteArrayOutputStream as a string. Each byte 144 * {@code b} in this stream is converted to a character {@code c} using the 145 * following function: 146 * {@code c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))}. This method is 147 * deprecated and either {@link #toString()} or {@link #toString(String)} 148 * should be used. 149 * 150 * @param hibyte 151 * the high byte of each resulting Unicode character. 152 * @return this stream's current contents as a string with the high byte set 153 * to {@code hibyte}. 154 * @deprecated Use {@link #toString()}. 155 */ 156 @Deprecated 157 public String toString(int hibyte) { 158 char[] newBuf = new char[size()]; 159 for (int i = 0; i < newBuf.length; i++) { 160 newBuf[i] = (char) (((hibyte & 0xff) << 8) | (buf[i] & 0xff)); 161 } 162 return new String(newBuf); 163 } 164 165 /** 166 * Returns the contents of this ByteArrayOutputStream as a string converted 167 * according to the encoding declared in {@code enc}. 168 * 169 * @param enc 170 * a string representing the encoding to use when translating 171 * this stream to a string. 172 * @return this stream's current contents as an encoded string. 173 * @throws UnsupportedEncodingException 174 * if the provided encoding is not supported. 175 */ 176 public String toString(String enc) throws UnsupportedEncodingException { 177 return new String(buf, 0, count, enc); 178 } 179 180 /** 181 * Writes {@code count} bytes from the byte array {@code buffer} starting at 182 * offset {@code index} to this stream. 183 * 184 * @param buffer 185 * the buffer to be written. 186 * @param offset 187 * the initial position in {@code buffer} to retrieve bytes. 188 * @param len 189 * the number of bytes of {@code buffer} to write. 190 * @throws NullPointerException 191 * if {@code buffer} is {@code null}. 192 * @throws IndexOutOfBoundsException 193 * if {@code offset < 0} or {@code len < 0}, or if 194 * {@code offset + len} is greater than the length of 195 * {@code buffer}. 196 */ 197 @Override 198 public synchronized void write(byte[] buffer, int offset, int len) { 199 // avoid int overflow 200 // BEGIN android-changed 201 // Exception priorities (in case of multiple errors) differ from 202 // RI, but are spec-compliant. 203 // removed redundant check, made implicit null check explicit, 204 // used (offset | len) < 0 instead of (offset < 0) || (len < 0) 205 // to safe one operation 206 if (buffer == null) { 207 throw new NullPointerException(Msg.getString("K0047")); 208 } 209 if ((offset | len) < 0 || len > buffer.length - offset) { 210 throw new IndexOutOfBoundsException(Msg.getString("K002f")); 211 } 212 // END android-changed 213 if (len == 0) { 214 return; 215 } 216 217 /* Expand if necessary */ 218 expand(len); 219 System.arraycopy(buffer, offset, buf, this.count, len); 220 this.count += len; 221 } 222 223 /** 224 * Writes the specified byte {@code oneByte} to the OutputStream. Only the 225 * low order byte of {@code oneByte} is written. 226 * 227 * @param oneByte 228 * the byte to be written. 229 */ 230 @Override 231 public synchronized void write(int oneByte) { 232 if (count == buf.length) { 233 expand(1); 234 } 235 buf[count++] = (byte) oneByte; 236 } 237 238 /** 239 * Takes the contents of this stream and writes it to the output stream 240 * {@code out}. 241 * 242 * @param out 243 * an OutputStream on which to write the contents of this stream. 244 * @throws IOException 245 * if an error occurs while writing to {@code out}. 246 */ 247 public synchronized void writeTo(OutputStream out) throws IOException { 248 out.write(buf, 0, count); 249 } 250} 251