UnsynchronizedByteArrayOutputStream.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. import org.apache.commons.io.build.AbstractOrigin;
  23. import org.apache.commons.io.build.AbstractStreamBuilder;
  24. import org.apache.commons.io.function.Uncheck;
  25. import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream;

  26. /**
  27.  * Implements a version of {@link AbstractByteArrayOutputStream} <strong>without</strong> any concurrent thread safety.
  28.  * <p>
  29.  * To build an instance, use {@link Builder}.
  30.  * </p>
  31.  *
  32.  * @see Builder
  33.  * @since 2.7
  34.  */
  35. //@NotThreadSafe
  36. public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream<UnsynchronizedByteArrayOutputStream> {

  37.     // @formatter:off
  38.     /**
  39.      * Builds a new {@link UnsynchronizedByteArrayOutputStream}.
  40.      *
  41.      * <p>
  42.      * Using File IO:
  43.      * </p>
  44.      * <pre>{@code
  45.      * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
  46.      *   .setBufferSize(8192)
  47.      *   .get();}
  48.      * </pre>
  49.      * <p>
  50.      * Using NIO Path:
  51.      * </p>
  52.      * <pre>{@code
  53.      * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder()
  54.      *   .setBufferSize(8192)
  55.      *   .get();}
  56.      * </pre>
  57.      *
  58.      * @see #get()
  59.      */
  60.     // @formatter:on
  61.     public static class Builder extends AbstractStreamBuilder<UnsynchronizedByteArrayOutputStream, Builder> {

  62.         /**
  63.          * Constructs a new builder of {@link UnsynchronizedByteArrayOutputStream}.
  64.          */
  65.         public Builder() {
  66.             // empty
  67.         }

  68.         /**
  69.          * Builds a new {@link UnsynchronizedByteArrayOutputStream}.
  70.          *
  71.          * <p>
  72.          * This builder uses the following aspects:
  73.          * </p>
  74.          * <ul>
  75.          * <li>{@link #getBufferSize()}</li>
  76.          * </ul>
  77.          *
  78.          * @return a new instance.
  79.          * @see AbstractOrigin#getByteArray()
  80.          * @see #getUnchecked()
  81.          */
  82.         @Override
  83.         public UnsynchronizedByteArrayOutputStream get() {
  84.             return new UnsynchronizedByteArrayOutputStream(getBufferSize());
  85.         }

  86.     }

  87.     /**
  88.      * Constructs a new {@link Builder}.
  89.      *
  90.      * @return a new {@link Builder}.
  91.      */
  92.     public static Builder builder() {
  93.         return new Builder();
  94.     }

  95.     /**
  96.      * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
  97.      * <p>
  98.      * This method is useful where,
  99.      * </p>
  100.      * <ul>
  101.      * <li>Source InputStream is slow.</li>
  102.      * <li>It has network resources associated, so we cannot keep it open for long time.</li>
  103.      * <li>It has network timeout associated.</li>
  104.      * </ul>
  105.      * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
  106.      * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
  107.      *
  108.      * @param input Stream to be fully buffered.
  109.      * @return A fully buffered stream.
  110.      * @throws IOException if an I/O error occurs.
  111.      */
  112.     public static InputStream toBufferedInputStream(final InputStream input) throws IOException {
  113.         return toBufferedInputStream(input, DEFAULT_SIZE);
  114.     }

  115.     /**
  116.      * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream.
  117.      * <p>
  118.      * This method is useful where,
  119.      * </p>
  120.      * <ul>
  121.      * <li>Source InputStream is slow.</li>
  122.      * <li>It has network resources associated, so we cannot keep it open for long time.</li>
  123.      * <li>It has network timeout associated.</li>
  124.      * </ul>
  125.      * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br>
  126.      * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}.
  127.      *
  128.      * @param input Stream to be fully buffered.
  129.      * @param size the initial buffer size
  130.      * @return A fully buffered stream.
  131.      * @throws IOException if an I/O error occurs.
  132.      */
  133.     public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException {
  134.         // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op
  135.         try (UnsynchronizedByteArrayOutputStream output = builder().setBufferSize(size).get()) {
  136.             output.write(input);
  137.             return output.toInputStream();
  138.         }
  139.     }

  140.     /**
  141.      * Constructs a new byte array output stream. The buffer capacity is initially
  142.      *
  143.      * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary.
  144.      * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}.
  145.      */
  146.     @Deprecated
  147.     public UnsynchronizedByteArrayOutputStream() {
  148.         this(DEFAULT_SIZE);
  149.     }

  150.     /**
  151.      * Constructs a new byte array output stream, with a buffer capacity of the specified size, in bytes.
  152.      *
  153.      * @param size the initial size
  154.      * @throws IllegalArgumentException if size is negative
  155.      * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. Will be private in 3.0.0.
  156.      */
  157.     @Deprecated
  158.     public UnsynchronizedByteArrayOutputStream(final int size) {
  159.         if (size < 0) {
  160.             throw new IllegalArgumentException("Negative initial size: " + size);
  161.         }
  162.         needNewBuffer(size);
  163.     }

  164.     /**
  165.      * @see java.io.ByteArrayOutputStream#reset()
  166.      */
  167.     @Override
  168.     public void reset() {
  169.         resetImpl();
  170.     }

  171.     @Override
  172.     public int size() {
  173.         return count;
  174.     }

  175.     @Override
  176.     public byte[] toByteArray() {
  177.         return toByteArrayImpl();
  178.     }

  179.     @Override
  180.     public InputStream toInputStream() {
  181.         // @formatter:off
  182.         return toInputStream((buffer, offset, length) -> Uncheck
  183.                 .get(() -> UnsynchronizedByteArrayInputStream.builder()
  184.                         .setByteArray(buffer)
  185.                         .setOffset(offset)
  186.                         .setLength(length)
  187.                         .get()));
  188.         // @formatter:on
  189.     }

  190.     @Override
  191.     public void write(final byte[] b, final int off, final int len) {
  192.         if (off < 0 || off > b.length || len < 0 || off + len > b.length || off + len < 0) {
  193.             throw new IndexOutOfBoundsException(String.format("offset=%,d, length=%,d", off, len));
  194.         }
  195.         if (len == 0) {
  196.             return;
  197.         }
  198.         writeImpl(b, off, len);
  199.     }

  200.     @Override
  201.     public int write(final InputStream in) throws IOException {
  202.         return writeImpl(in);
  203.     }

  204.     @Override
  205.     public void write(final int b) {
  206.         writeImpl(b);
  207.     }

  208.     @Override
  209.     public void writeTo(final OutputStream out) throws IOException {
  210.         writeToImpl(out);
  211.     }
  212. }