1 /* 2 * Copyright (c) 1994, 2017, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.io; 27 28 import java.nio.charset.Charset; 29 import java.util.Arrays; 30 31 /** 32 * This class implements an output stream in which the data is 33 * written into a byte array. The buffer automatically grows as data 34 * is written to it. 35 * The data can be retrieved using {@code toByteArray()} and 36 * {@code toString()}. 37 * <p> 38 * Closing a {@code ByteArrayOutputStream} has no effect. The methods in 39 * this class can be called after the stream has been closed without 40 * generating an {@code IOException}. 41 * 42 * @author Arthur van Hoff 43 * @since 1.0 44 */ 45 46 public class ByteArrayOutputStream extends OutputStream { 47 48 /** 49 * The buffer where data is stored. 50 */ 51 protected byte buf[]; 52 53 /** 54 * The number of valid bytes in the buffer. 55 */ 56 protected int count; 57 58 /** 59 * Creates a new byte array output stream. The buffer capacity is 60 * initially 32 bytes, though its size increases if necessary. 61 */ 62 public ByteArrayOutputStream() { 63 this(32); 64 } 65 66 /** 67 * Creates a new byte array output stream, with a buffer capacity of 68 * the specified size, in bytes. 69 * 70 * @param size the initial size. 71 * @exception IllegalArgumentException if size is negative. 72 */ 73 public ByteArrayOutputStream(int size) { 74 if (size < 0) { 75 throw new IllegalArgumentException("Negative initial size: " 76 + size); 77 } 78 buf = new byte[size]; 79 } 80 81 /** 82 * Increases the capacity if necessary to ensure that it can hold 83 * at least the number of elements specified by the minimum 84 * capacity argument. 85 * 86 * @param minCapacity the desired minimum capacity 87 * @throws OutOfMemoryError if {@code minCapacity < 0}. This is 88 * interpreted as a request for the unsatisfiably large capacity 89 * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}. 90 */ 91 private void ensureCapacity(int minCapacity) { 92 // overflow-conscious code 93 if (minCapacity - buf.length > 0) 94 grow(minCapacity); 95 } 96 97 /** 98 * The maximum size of array to allocate. 99 * Some VMs reserve some header words in an array. 100 * Attempts to allocate larger arrays may result in 101 * OutOfMemoryError: Requested array size exceeds VM limit 102 */ 103 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 104 105 /** 106 * Increases the capacity to ensure that it can hold at least the 107 * number of elements specified by the minimum capacity argument. 108 * 109 * @param minCapacity the desired minimum capacity 110 */ 111 private void grow(int minCapacity) { 112 // overflow-conscious code 113 int oldCapacity = buf.length; 114 int newCapacity = oldCapacity << 1; 115 if (newCapacity - minCapacity < 0) 116 newCapacity = minCapacity; 117 if (newCapacity - MAX_ARRAY_SIZE > 0) 118 newCapacity = hugeCapacity(minCapacity); 119 buf = Arrays.copyOf(buf, newCapacity); 120 } 121 122 private static int hugeCapacity(int minCapacity) { 123 if (minCapacity < 0) // overflow 124 throw new OutOfMemoryError(); 125 return (minCapacity > MAX_ARRAY_SIZE) ? 126 Integer.MAX_VALUE : 127 MAX_ARRAY_SIZE; 128 } 129 130 /** 131 * Writes the specified byte to this byte array output stream. 132 * 133 * @param b the byte to be written. 134 */ 135 public synchronized void write(int b) { 136 ensureCapacity(count + 1); 137 buf[count] = (byte) b; 138 count += 1; 139 } 140 141 /** 142 * Writes {@code len} bytes from the specified byte array 143 * starting at offset {@code off} to this byte array output stream. 144 * 145 * @param b the data. 146 * @param off the start offset in the data. 147 * @param len the number of bytes to write. 148 */ 149 public synchronized void write(byte b[], int off, int len) { 150 if ((off < 0) || (off > b.length) || (len < 0) || 151 ((off + len) - b.length > 0)) { 152 throw new IndexOutOfBoundsException(); 153 } 154 ensureCapacity(count + len); 155 System.arraycopy(b, off, buf, count, len); 156 count += len; 157 } 158 159 /** 160 * Writes the complete contents of this byte array output stream to 161 * the specified output stream argument, as if by calling the output 162 * stream's write method using {@code out.write(buf, 0, count)}. 163 * 164 * @param out the output stream to which to write the data. 165 * @exception IOException if an I/O error occurs. 166 */ 167 public synchronized void writeTo(OutputStream out) throws IOException { 168 out.write(buf, 0, count); 169 } 170 171 /** 172 * Resets the {@code count} field of this byte array output 173 * stream to zero, so that all currently accumulated output in the 174 * output stream is discarded. The output stream can be used again, 175 * reusing the already allocated buffer space. 176 * 177 * @see java.io.ByteArrayInputStream#count 178 */ 179 public synchronized void reset() { 180 count = 0; 181 } 182 183 /** 184 * Creates a newly allocated byte array. Its size is the current 185 * size of this output stream and the valid contents of the buffer 186 * have been copied into it. 187 * 188 * @return the current contents of this output stream, as a byte array. 189 * @see java.io.ByteArrayOutputStream#size() 190 */ 191 public synchronized byte[] toByteArray() { 192 return Arrays.copyOf(buf, count); 193 } 194 195 /** 196 * Returns the current size of the buffer. 197 * 198 * @return the value of the {@code count} field, which is the number 199 * of valid bytes in this output stream. 200 * @see java.io.ByteArrayOutputStream#count 201 */ 202 public synchronized int size() { 203 return count; 204 } 205 206 /** 207 * Converts the buffer's contents into a string decoding bytes using the 208 * platform's default character set. The length of the new {@code String} 209 * is a function of the character set, and hence may not be equal to the 210 * size of the buffer. 211 * 212 * <p> This method always replaces malformed-input and unmappable-character 213 * sequences with the default replacement string for the platform's 214 * default character set. The {@linkplain java.nio.charset.CharsetDecoder} 215 * class should be used when more control over the decoding process is 216 * required. 217 * 218 * @return String decoded from the buffer's contents. 219 * @since 1.1 220 */ 221 public synchronized String toString() { 222 return new String(buf, 0, count); 223 } 224 225 /** 226 * Converts the buffer's contents into a string by decoding the bytes using 227 * the named {@link java.nio.charset.Charset charset}. 228 * 229 * <p> This method is equivalent to {@code #toString(charset)} that takes a 230 * {@link java.nio.charset.Charset charset}. 231 * 232 * <p> An invocation of this method of the form 233 * 234 * <pre> {@code 235 * ByteArrayOutputStream b = ... 236 * b.toString("UTF-8") 237 * } 238 * </pre> 239 * 240 * behaves in exactly the same way as the expression 241 * 242 * <pre> {@code 243 * ByteArrayOutputStream b = ... 244 * b.toString(StandardCharsets.UTF_8) 245 * } 246 * </pre> 247 * 248 * 249 * @param charsetName the name of a supported 250 * {@link java.nio.charset.Charset charset} 251 * @return String decoded from the buffer's contents. 252 * @exception UnsupportedEncodingException 253 * If the named charset is not supported 254 * @since 1.1 255 */ 256 public synchronized String toString(String charsetName) 257 throws UnsupportedEncodingException 258 { 259 return new String(buf, 0, count, charsetName); 260 } 261 262 /** 263 * Converts the buffer's contents into a string by decoding the bytes using 264 * the specified {@link java.nio.charset.Charset charset}. The length of the new 265 * {@code String} is a function of the charset, and hence may not be equal 266 * to the length of the byte array. 267 * 268 * <p> This method always replaces malformed-input and unmappable-character 269 * sequences with the charset's default replacement string. The {@link 270 * java.nio.charset.CharsetDecoder} class should be used when more control 271 * over the decoding process is required. 272 * 273 * @param charset the {@linkplain java.nio.charset.Charset charset} 274 * to be used to decode the {@code bytes} 275 * @return String decoded from the buffer's contents. 276 * @since 10 277 */ 278 public synchronized String toString(Charset charset) { 279 return new String(buf, 0, count, charset); 280 } 281 282 /** 283 * Creates a newly allocated string. Its size is the current size of 284 * the output stream and the valid contents of the buffer have been 285 * copied into it. Each character <i>c</i> in the resulting string is 286 * constructed from the corresponding element <i>b</i> in the byte 287 * array such that: 288 * <blockquote><pre>{@code 289 * c == (char)(((hibyte & 0xff) << 8) | (b & 0xff)) 290 * }</pre></blockquote> 291 * 292 * @deprecated This method does not properly convert bytes into characters. 293 * As of JDK 1.1, the preferred way to do this is via the 294 * {@link #toString(String charsetName)} or {@link #toString(Charset charset)} 295 * method, which takes an encoding-name or charset argument, 296 * or the {@code toString()} method, which uses the platform's default 297 * character encoding. 298 * 299 * @param hibyte the high byte of each resulting Unicode character. 300 * @return the current contents of the output stream, as a string. 301 * @see java.io.ByteArrayOutputStream#size() 302 * @see java.io.ByteArrayOutputStream#toString(String) 303 * @see java.io.ByteArrayOutputStream#toString() 304 */ 305 @Deprecated 306 public synchronized String toString(int hibyte) { 307 return new String(buf, hibyte, 0, count); 308 } 309 310 /** 311 * Closing a {@code ByteArrayOutputStream} has no effect. The methods in 312 * this class can be called after the stream has been closed without 313 * generating an {@code IOException}. 314 */ 315 public void close() throws IOException { 316 } 317 318 }