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 } else if (len == 0) { 059 return; 060 } 061 writeImpl(b, off, len); 062 } 063 064 @Override 065 public void write(final int b) { 066 writeImpl(b); 067 } 068 069 @Override 070 public int write(final InputStream in) throws IOException { 071 return writeImpl(in); 072 } 073 074 @Override 075 public int size() { 076 return count; 077 } 078 079 /** 080 * @see java.io.ByteArrayOutputStream#reset() 081 */ 082 @Override 083 public void reset() { 084 resetImpl(); 085 } 086 087 @Override 088 public void writeTo(final OutputStream out) throws IOException { 089 writeToImpl(out); 090 } 091 092 /** 093 * Fetches entire contents of an <code>InputStream</code> and represent same data as result InputStream. 094 * <p> 095 * This method is useful where, 096 * </p> 097 * <ul> 098 * <li>Source InputStream is slow.</li> 099 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 100 * <li>It has network timeout associated.</li> 101 * </ul> 102 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 103 * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>. 104 * 105 * @param input Stream to be fully buffered. 106 * @return A fully buffered stream. 107 * @throws IOException if an I/O error occurs 108 */ 109 public static InputStream toBufferedInputStream(final InputStream input) throws IOException { 110 return toBufferedInputStream(input, DEFAULT_SIZE); 111 } 112 113 /** 114 * Fetches entire contents of an <code>InputStream</code> and represent same data as result InputStream. 115 * <p> 116 * This method is useful where, 117 * </p> 118 * <ul> 119 * <li>Source InputStream is slow.</li> 120 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 121 * <li>It has network timeout associated.</li> 122 * </ul> 123 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[].<br> 124 * This method buffers the input internally, so there is no need to use a <code>BufferedInputStream</code>. 125 * 126 * @param input Stream to be fully buffered. 127 * @param size the initial buffer size 128 * @return A fully buffered stream. 129 * @throws IOException if an I/O error occurs 130 */ 131 public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { 132 // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op 133 try (final UnsynchronizedByteArrayOutputStream output = new UnsynchronizedByteArrayOutputStream(size)) { 134 output.write(input); 135 return output.toInputStream(); 136 } 137 } 138 139 @Override 140 public InputStream toInputStream() { 141 return toInputStream(UnsynchronizedByteArrayInputStream::new); 142 } 143 144 @Override 145 public byte[] toByteArray() { 146 return toByteArrayImpl(); 147 } 148}