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