View Javadoc
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    *      https://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  package org.apache.commons.io.output;
18  
19  import java.io.BufferedInputStream;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.OutputStream;
23  
24  import org.apache.commons.io.IOUtils;
25  
26  /**
27   * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization.
28   */
29  //@ThreadSafe
30  public class ByteArrayOutputStream extends AbstractByteArrayOutputStream<ByteArrayOutputStream> {
31  
32      /**
33       * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
34       * <p>
35       * This method is useful where,
36       * </p>
37       * <ul>
38       * <li>Source InputStream is slow.</li>
39       * <li>It has network resources associated, so we cannot keep it open for long time.</li>
40       * <li>It has network timeout associated.</li>
41       * </ul>
42       * <p>
43       * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
44       * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
45       * </p>
46       *
47       * @param input Stream to be fully buffered.
48       * @return A fully buffered stream.
49       * @throws IOException if an I/O error occurs.
50       * @since 2.0
51       */
52      public static InputStream toBufferedInputStream(final InputStream input)
53              throws IOException {
54          return toBufferedInputStream(input, DEFAULT_SIZE);
55      }
56  
57      /**
58       * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
59       * <p>
60       * This method is useful where,
61       * </p>
62       * <ul>
63       * <li>Source InputStream is slow.</li>
64       * <li>It has network resources associated, so we cannot keep it open for long time.</li>
65       * <li>It has network timeout associated.</li>
66       * </ul>
67       * <p>
68       * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
69       * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
70       * </p>
71       *
72       * @param input Stream to be fully buffered.
73       * @param size  the initial buffer size.
74       * @return A fully buffered stream.
75       * @throws IOException if an I/O error occurs.
76       * @since 2.5
77       */
78      public static InputStream toBufferedInputStream(final InputStream input, final int size)
79          throws IOException {
80          try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) {
81              output.write(input);
82              return output.toInputStream();
83          }
84      }
85  
86      /**
87       * Constructs a new byte array output stream. The buffer capacity is
88       * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
89       */
90      public ByteArrayOutputStream() {
91          this(DEFAULT_SIZE);
92      }
93  
94      /**
95       * Constructs a new byte array output stream, with a buffer capacity of
96       * the specified size, in bytes.
97       *
98       * @param size  the initial size
99       * @throws IllegalArgumentException if size is negative
100      */
101     public ByteArrayOutputStream(final int size) {
102         if (size < 0) {
103             throw new IllegalArgumentException("Negative initial size: " + size);
104         }
105         synchronized (this) {
106             needNewBuffer(size);
107         }
108     }
109 
110     /**
111      * @see java.io.ByteArrayOutputStream#reset()
112      */
113     @Override
114     public synchronized void reset() {
115         resetImpl();
116     }
117 
118     @Override
119     public synchronized int size() {
120         return count;
121     }
122 
123     @Override
124     public synchronized byte[] toByteArray() {
125         return toByteArrayImpl();
126     }
127 
128     @Override
129     public synchronized InputStream toInputStream() {
130         return toInputStream(java.io.ByteArrayInputStream::new);
131     }
132 
133     @Override
134     public void write(final byte[] b, final int off, final int len) {
135         IOUtils.checkFromIndexSize(b, off, len);
136         if (len == 0) {
137             return;
138         }
139         synchronized (this) {
140             writeImpl(b, off, len);
141         }
142     }
143 
144     @Override
145     public synchronized int write(final InputStream in) throws IOException {
146         return writeImpl(in);
147     }
148 
149     @Override
150     public synchronized void write(final int b) {
151         writeImpl(b);
152     }
153 
154     @Override
155     public synchronized void writeTo(final OutputStream out) throws IOException {
156         writeToImpl(out);
157     }
158 }