ByteArrayOutputStream.java

  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. package org.apache.commons.io.output;

  18. import java.io.BufferedInputStream;
  19. import java.io.IOException;
  20. import java.io.InputStream;
  21. import java.io.OutputStream;

  22. /**
  23.  * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization.
  24.  */
  25. //@ThreadSafe
  26. public class ByteArrayOutputStream extends AbstractByteArrayOutputStream<ByteArrayOutputStream> {

  27.     /**
  28.      * Fetches entire contents of an {@link InputStream} and represent
  29.      * same data as result InputStream.
  30.      * <p>
  31.      * This method is useful where,
  32.      * </p>
  33.      * <ul>
  34.      * <li>Source InputStream is slow.</li>
  35.      * <li>It has network resources associated, so we cannot keep it open for
  36.      * long time.</li>
  37.      * <li>It has network timeout associated.</li>
  38.      * </ul>
  39.      * It can be used in favor of {@link #toByteArray()}, since it
  40.      * avoids unnecessary allocation and copy of byte[].<br>
  41.      * This method buffers the input internally, so there is no need to use a
  42.      * {@link BufferedInputStream}.
  43.      *
  44.      * @param input Stream to be fully buffered.
  45.      * @return A fully buffered stream.
  46.      * @throws IOException if an I/O error occurs.
  47.      * @since 2.0
  48.      */
  49.     public static InputStream toBufferedInputStream(final InputStream input)
  50.             throws IOException {
  51.         return toBufferedInputStream(input, DEFAULT_SIZE);
  52.     }

  53.     /**
  54.      * Fetches entire contents of an {@link InputStream} and represent
  55.      * same data as result InputStream.
  56.      * <p>
  57.      * This method is useful where,
  58.      * </p>
  59.      * <ul>
  60.      * <li>Source InputStream is slow.</li>
  61.      * <li>It has network resources associated, so we cannot keep it open for
  62.      * long time.</li>
  63.      * <li>It has network timeout associated.</li>
  64.      * </ul>
  65.      * It can be used in favor of {@link #toByteArray()}, since it
  66.      * avoids unnecessary allocation and copy of byte[].<br>
  67.      * This method buffers the input internally, so there is no need to use a
  68.      * {@link BufferedInputStream}.
  69.      *
  70.      * @param input Stream to be fully buffered.
  71.      * @param size the initial buffer size
  72.      * @return A fully buffered stream.
  73.      * @throws IOException if an I/O error occurs.
  74.      * @since 2.5
  75.      */
  76.     public static InputStream toBufferedInputStream(final InputStream input, final int size)
  77.         throws IOException {
  78.         try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) {
  79.             output.write(input);
  80.             return output.toInputStream();
  81.         }
  82.     }

  83.     /**
  84.      * Constructs a new byte array output stream. The buffer capacity is
  85.      * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
  86.      */
  87.     public ByteArrayOutputStream() {
  88.         this(DEFAULT_SIZE);
  89.     }

  90.     /**
  91.      * Constructs a new byte array output stream, with a buffer capacity of
  92.      * the specified size, in bytes.
  93.      *
  94.      * @param size  the initial size
  95.      * @throws IllegalArgumentException if size is negative
  96.      */
  97.     public ByteArrayOutputStream(final int size) {
  98.         if (size < 0) {
  99.             throw new IllegalArgumentException("Negative initial size: " + size);
  100.         }
  101.         synchronized (this) {
  102.             needNewBuffer(size);
  103.         }
  104.     }

  105.     /**
  106.      * @see java.io.ByteArrayOutputStream#reset()
  107.      */
  108.     @Override
  109.     public synchronized void reset() {
  110.         resetImpl();
  111.     }

  112.     @Override
  113.     public synchronized int size() {
  114.         return count;
  115.     }

  116.     @Override
  117.     public synchronized byte[] toByteArray() {
  118.         return toByteArrayImpl();
  119.     }

  120.     @Override
  121.     public synchronized InputStream toInputStream() {
  122.         return toInputStream(java.io.ByteArrayInputStream::new);
  123.     }

  124.     @Override
  125.     public void write(final byte[] b, final int off, final int len) {
  126.         if (off < 0
  127.                 || off > b.length
  128.                 || len < 0
  129.                 || off + len > b.length
  130.                 || off + len < 0) {
  131.             throw new IndexOutOfBoundsException();
  132.         }
  133.         if (len == 0) {
  134.             return;
  135.         }
  136.         synchronized (this) {
  137.             writeImpl(b, off, len);
  138.         }
  139.     }

  140.     @Override
  141.     public synchronized int write(final InputStream in) throws IOException {
  142.         return writeImpl(in);
  143.     }

  144.     @Override
  145.     public synchronized void write(final int b) {
  146.         writeImpl(b);
  147.     }

  148.     @Override
  149.     public synchronized void writeTo(final OutputStream out) throws IOException {
  150.         writeToImpl(out);
  151.     }
  152. }