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