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 * https://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 java.io.BufferedInputStream; 020import java.io.IOException; 021import java.io.InputStream; 022import java.io.OutputStream; 023 024import org.apache.commons.io.IOUtils; 025 026/** 027 * Implements a ThreadSafe version of {@link AbstractByteArrayOutputStream} using instance synchronization. 028 */ 029//@ThreadSafe 030public class ByteArrayOutputStream extends AbstractByteArrayOutputStream<ByteArrayOutputStream> { 031 032 /** 033 * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream. 034 * <p> 035 * This method is useful where, 036 * </p> 037 * <ul> 038 * <li>Source InputStream is slow.</li> 039 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 040 * <li>It has network timeout associated.</li> 041 * </ul> 042 * <p> 043 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 044 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}. 045 * </p> 046 * 047 * @param input Stream to be fully buffered. 048 * @return A fully buffered stream. 049 * @throws IOException if an I/O error occurs. 050 * @since 2.0 051 */ 052 public static InputStream toBufferedInputStream(final InputStream input) 053 throws IOException { 054 return toBufferedInputStream(input, DEFAULT_SIZE); 055 } 056 057 /** 058 * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream. 059 * <p> 060 * This method is useful where, 061 * </p> 062 * <ul> 063 * <li>Source InputStream is slow.</li> 064 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 065 * <li>It has network timeout associated.</li> 066 * </ul> 067 * <p> 068 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 069 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}. 070 * </p> 071 * 072 * @param input Stream to be fully buffered. 073 * @param size the initial buffer size. 074 * @return A fully buffered stream. 075 * @throws IOException if an I/O error occurs. 076 * @since 2.5 077 */ 078 public static InputStream toBufferedInputStream(final InputStream input, final int size) 079 throws IOException { 080 try (ByteArrayOutputStream output = new ByteArrayOutputStream(size)) { 081 output.write(input); 082 return output.toInputStream(); 083 } 084 } 085 086 /** 087 * Constructs a new byte array output stream. The buffer capacity is 088 * initially {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 089 */ 090 public ByteArrayOutputStream() { 091 this(DEFAULT_SIZE); 092 } 093 094 /** 095 * Constructs a new byte array output stream, with a buffer capacity of 096 * the specified size, in bytes. 097 * 098 * @param size the initial size 099 * @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}