1 /* 2 * Copyright (c) 1994, 2013, 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.util.Arrays; 29 30 /** 31 * This class implements an output stream in which the data is 32 * written into a byte array. The buffer automatically grows as data 33 * is written to it. 34 * The data can be retrieved using <code>toByteArray()</code> and 35 * <code>toString()</code>. 36 * <p> 37 * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 38 * this class can be called after the stream has been closed without 39 * generating an <tt>IOException</tt>. 40 * 41 * @author Arthur van Hoff 42 * @since JDK1.0 43 */ 44 45 public class ByteArrayOutputStream extends OutputStream { 46 47 /** 48 * The buffer where data is stored. 49 */ 50 protected byte buf[]; 51 52 /** 53 * The number of valid bytes in the buffer. 54 */ 55 protected int count; 56 57 /** 58 * Creates a new byte array output stream. The buffer capacity is 59 * initially 32 bytes, though its size increases if necessary. 60 */ ByteArrayOutputStream()61 public ByteArrayOutputStream() { 62 this(32); 63 } 64 65 /** 66 * Creates a new byte array output stream, with a buffer capacity of 67 * the specified size, in bytes. 68 * 69 * @param size the initial size. 70 * @exception IllegalArgumentException if size is negative. 71 */ ByteArrayOutputStream(int size)72 public ByteArrayOutputStream(int size) { 73 if (size < 0) { 74 throw new IllegalArgumentException("Negative initial size: " 75 + size); 76 } 77 buf = new byte[size]; 78 } 79 80 /** 81 * Increases the capacity if necessary to ensure that it can hold 82 * at least the number of elements specified by the minimum 83 * capacity argument. 84 * 85 * @param minCapacity the desired minimum capacity 86 * @throws OutOfMemoryError if {@code minCapacity < 0}. This is 87 * interpreted as a request for the unsatisfiably large capacity 88 * {@code (long) Integer.MAX_VALUE + (minCapacity - Integer.MAX_VALUE)}. 89 */ ensureCapacity(int minCapacity)90 private void ensureCapacity(int minCapacity) { 91 // overflow-conscious code 92 if (minCapacity - buf.length > 0) 93 grow(minCapacity); 94 } 95 96 /** 97 * The maximum size of array to allocate. 98 * Some VMs reserve some header words in an array. 99 * Attempts to allocate larger arrays may result in 100 * OutOfMemoryError: Requested array size exceeds VM limit 101 */ 102 private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; 103 104 /** 105 * Increases the capacity to ensure that it can hold at least the 106 * number of elements specified by the minimum capacity argument. 107 * 108 * @param minCapacity the desired minimum capacity 109 */ grow(int minCapacity)110 private void grow(int minCapacity) { 111 // overflow-conscious code 112 int oldCapacity = buf.length; 113 int newCapacity = oldCapacity << 1; 114 if (newCapacity - minCapacity < 0) 115 newCapacity = minCapacity; 116 if (newCapacity - MAX_ARRAY_SIZE > 0) 117 newCapacity = hugeCapacity(minCapacity); 118 buf = Arrays.copyOf(buf, newCapacity); 119 } 120 hugeCapacity(int minCapacity)121 private static int hugeCapacity(int minCapacity) { 122 if (minCapacity < 0) // overflow 123 throw new OutOfMemoryError(); 124 return (minCapacity > MAX_ARRAY_SIZE) ? 125 Integer.MAX_VALUE : 126 MAX_ARRAY_SIZE; 127 } 128 129 /** 130 * Writes the specified byte to this byte array output stream. 131 * 132 * @param b the byte to be written. 133 */ write(int b)134 public synchronized void write(int b) { 135 ensureCapacity(count + 1); 136 buf[count] = (byte) b; 137 count += 1; 138 } 139 140 /** 141 * Writes <code>len</code> bytes from the specified byte array 142 * starting at offset <code>off</code> to this byte array output stream. 143 * 144 * @param b the data. 145 * @param off the start offset in the data. 146 * @param len the number of bytes to write. 147 */ write(byte b[], int off, int len)148 public synchronized void write(byte b[], int off, int len) { 149 if ((off < 0) || (off > b.length) || (len < 0) || 150 ((off + len) - b.length > 0)) { 151 throw new IndexOutOfBoundsException(); 152 } 153 ensureCapacity(count + len); 154 System.arraycopy(b, off, buf, count, len); 155 count += len; 156 } 157 158 /** 159 * Writes the complete contents of this byte array output stream to 160 * the specified output stream argument, as if by calling the output 161 * stream's write method using <code>out.write(buf, 0, count)</code>. 162 * 163 * @param out the output stream to which to write the data. 164 * @exception IOException if an I/O error occurs. 165 */ writeTo(OutputStream out)166 public synchronized void writeTo(OutputStream out) throws IOException { 167 out.write(buf, 0, count); 168 } 169 170 /** 171 * Resets the <code>count</code> field of this byte array output 172 * stream to zero, so that all currently accumulated output in the 173 * output stream is discarded. The output stream can be used again, 174 * reusing the already allocated buffer space. 175 * 176 * @see java.io.ByteArrayInputStream#count 177 */ reset()178 public synchronized void reset() { 179 count = 0; 180 } 181 182 /** 183 * Creates a newly allocated byte array. Its size is the current 184 * size of this output stream and the valid contents of the buffer 185 * have been copied into it. 186 * 187 * @return the current contents of this output stream, as a byte array. 188 * @see java.io.ByteArrayOutputStream#size() 189 */ toByteArray()190 public synchronized byte toByteArray()[] { 191 return Arrays.copyOf(buf, count); 192 } 193 194 /** 195 * Returns the current size of the buffer. 196 * 197 * @return the value of the <code>count</code> field, which is the number 198 * of valid bytes in this output stream. 199 * @see java.io.ByteArrayOutputStream#count 200 */ size()201 public synchronized int size() { 202 return count; 203 } 204 205 /** 206 * Converts the buffer's contents into a string decoding bytes using the 207 * platform's default character set. The length of the new <tt>String</tt> 208 * is a function of the character set, and hence may not be equal to the 209 * size of the buffer. 210 * 211 * <p> This method always replaces malformed-input and unmappable-character 212 * sequences with the default replacement string for the platform's 213 * default character set. The {@linkplain java.nio.charset.CharsetDecoder} 214 * class should be used when more control over the decoding process is 215 * required. 216 * 217 * @return String decoded from the buffer's contents. 218 * @since JDK1.1 219 */ toString()220 public synchronized String toString() { 221 return new String(buf, 0, count); 222 } 223 224 /** 225 * Converts the buffer's contents into a string by decoding the bytes using 226 * the named {@link java.nio.charset.Charset charset}. The length of the new 227 * <tt>String</tt> is a function of the charset, and hence may not be equal 228 * to the length of the byte array. 229 * 230 * <p> This method always replaces malformed-input and unmappable-character 231 * sequences with this charset's default replacement string. The {@link 232 * java.nio.charset.CharsetDecoder} class should be used when more control 233 * over the decoding process is required. 234 * 235 * @param charsetName the name of a supported 236 * {@link java.nio.charset.Charset charset} 237 * @return String decoded from the buffer's contents. 238 * @exception UnsupportedEncodingException 239 * If the named charset is not supported 240 * @since JDK1.1 241 */ toString(String charsetName)242 public synchronized String toString(String charsetName) 243 throws UnsupportedEncodingException 244 { 245 return new String(buf, 0, count, charsetName); 246 } 247 248 /** 249 * Creates a newly allocated string. Its size is the current size of 250 * the output stream and the valid contents of the buffer have been 251 * copied into it. Each character <i>c</i> in the resulting string is 252 * constructed from the corresponding element <i>b</i> in the byte 253 * array such that: 254 * <blockquote><pre> 255 * c == (char)(((hibyte & 0xff) << 8) | (b & 0xff)) 256 * </pre></blockquote> 257 * 258 * @deprecated This method does not properly convert bytes into characters. 259 * As of JDK 1.1, the preferred way to do this is via the 260 * <code>toString(String enc)</code> method, which takes an encoding-name 261 * argument, or the <code>toString()</code> method, which uses the 262 * platform's default character encoding. 263 * 264 * @param hibyte the high byte of each resulting Unicode character. 265 * @return the current contents of the output stream, as a string. 266 * @see java.io.ByteArrayOutputStream#size() 267 * @see java.io.ByteArrayOutputStream#toString(String) 268 * @see java.io.ByteArrayOutputStream#toString() 269 */ 270 @Deprecated toString(int hibyte)271 public synchronized String toString(int hibyte) { 272 return new String(buf, hibyte, 0, count); 273 } 274 275 /** 276 * Closing a <tt>ByteArrayOutputStream</tt> has no effect. The methods in 277 * this class can be called after the stream has been closed without 278 * generating an <tt>IOException</tt>. 279 */ close()280 public void close() throws IOException { 281 } 282 283 } 284