001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.io.output; 018 019import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; 020 021import java.io.IOException; 022import java.io.InputStream; 023import java.io.OutputStream; 024 025/** 026 * Implements a version of {@link AbstractByteArrayOutputStream} <b>without</b> any concurrent thread safety. 027 * 028 * @since 2.7 029 */ 030//@NotThreadSafe 031public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream { 032 033 /** 034 * Creates a new byte array output stream. The buffer capacity is initially 035 * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 036 */ 037 public UnsynchronizedByteArrayOutputStream() { 038 this(DEFAULT_SIZE); 039 } 040 041 /** 042 * Creates a new byte array output stream, with a buffer capacity of the specified size, in bytes. 043 * 044 * @param size the initial size 045 * @throws IllegalArgumentException if size is negative 046 */ 047 public UnsynchronizedByteArrayOutputStream(final int size) { 048 if (size < 0) { 049 throw new IllegalArgumentException("Negative initial size: " + size); 050 } 051 needNewBuffer(size); 052 } 053 054 @Override 055 public void write(final byte[] b, final int off, final int len) { 056 if ((off < 0) || (off > b.length) || (len < 0) || ((off + len) > b.length) || ((off + len) < 0)) { 057 throw new IndexOutOfBoundsException(String.format("offset=%,d, length=%,d", off, len)); 058 } 059 if (len == 0) { 060 return; 061 } 062 writeImpl(b, off, len); 063 } 064 065 @Override 066 public void write(final int b) { 067 writeImpl(b); 068 } 069 070 @Override 071 public int write(final InputStream in) throws IOException { 072 return writeImpl(in); 073 } 074 075 @Override 076 public int size() { 077 return count; 078 } 079 080 /** 081 * @see java.io.ByteArrayOutputStream#reset() 082 */ 083 @Override 084 public void reset() { 085 resetImpl(); 086 } 087 088 @Override 089 public void writeTo(final OutputStream out) throws IOException { 090 writeToImpl(out); 091 } 092 093 /** 094 * Fetches entire contents of an {@code InputStream} and represent same data as result InputStream. 095 * <p> 096 * This method is useful where, 097 * </p> 098 * <ul> 099 * <li>Source InputStream is slow.</li> 100 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 101 * <li>It has network timeout associated.</li> 102 * </ul> 103 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 104 * This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. 105 * 106 * @param input Stream to be fully buffered. 107 * @return A fully buffered stream. 108 * @throws IOException if an I/O error occurs. 109 */ 110 public static InputStream toBufferedInputStream(final InputStream input) throws IOException { 111 return toBufferedInputStream(input, DEFAULT_SIZE); 112 } 113 114 /** 115 * Fetches entire contents of an {@code InputStream} and represent same data as result InputStream. 116 * <p> 117 * This method is useful where, 118 * </p> 119 * <ul> 120 * <li>Source InputStream is slow.</li> 121 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 122 * <li>It has network timeout associated.</li> 123 * </ul> 124 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 125 * This method buffers the input internally, so there is no need to use a {@code BufferedInputStream}. 126 * 127 * @param input Stream to be fully buffered. 128 * @param size the initial buffer size 129 * @return A fully buffered stream. 130 * @throws IOException if an I/O error occurs. 131 */ 132 public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { 133 // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op 134 try (final UnsynchronizedByteArrayOutputStream output = new UnsynchronizedByteArrayOutputStream(size)) { 135 output.write(input); 136 return output.toInputStream(); 137 } 138 } 139 140 @Override 141 public InputStream toInputStream() { 142 return toInputStream(UnsynchronizedByteArrayInputStream::new); 143 } 144 145 @Override 146 public byte[] toByteArray() { 147 return toByteArrayImpl(); 148 } 149}