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; 025import org.apache.commons.io.build.AbstractOrigin; 026import org.apache.commons.io.build.AbstractStreamBuilder; 027import org.apache.commons.io.function.Uncheck; 028import org.apache.commons.io.input.UnsynchronizedByteArrayInputStream; 029 030/** 031 * Implements a version of {@link AbstractByteArrayOutputStream} <strong>without</strong> any concurrent thread safety. 032 * <p> 033 * To build an instance, use {@link Builder}. 034 * </p> 035 * 036 * @see Builder 037 * @since 2.7 038 */ 039//@NotThreadSafe 040public final class UnsynchronizedByteArrayOutputStream extends AbstractByteArrayOutputStream<UnsynchronizedByteArrayOutputStream> { 041 042 // @formatter:off 043 /** 044 * Builds a new {@link UnsynchronizedByteArrayOutputStream}. 045 * 046 * <p> 047 * Using File IO: 048 * </p> 049 * <pre>{@code 050 * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder() 051 * .setBufferSize(8192) 052 * .get();} 053 * </pre> 054 * <p> 055 * Using NIO Path: 056 * </p> 057 * <pre>{@code 058 * UnsynchronizedByteArrayOutputStream s = UnsynchronizedByteArrayOutputStream.builder() 059 * .setBufferSize(8192) 060 * .get();} 061 * </pre> 062 * 063 * @see #get() 064 */ 065 // @formatter:on 066 public static class Builder extends AbstractStreamBuilder<UnsynchronizedByteArrayOutputStream, Builder> { 067 068 /** 069 * Constructs a new builder of {@link UnsynchronizedByteArrayOutputStream}. 070 */ 071 public Builder() { 072 // empty 073 } 074 075 /** 076 * Builds a new {@link UnsynchronizedByteArrayOutputStream}. 077 * 078 * <p> 079 * This builder uses the following aspects: 080 * </p> 081 * <ul> 082 * <li>{@link #getBufferSize()}</li> 083 * </ul> 084 * 085 * @return a new instance. 086 * @see AbstractOrigin#getByteArray() 087 * @see #getUnchecked() 088 */ 089 @Override 090 public UnsynchronizedByteArrayOutputStream get() { 091 return new UnsynchronizedByteArrayOutputStream(this); 092 } 093 094 } 095 096 /** 097 * Constructs a new {@link Builder}. 098 * 099 * @return a new {@link Builder}. 100 */ 101 public static Builder builder() { 102 return new Builder(); 103 } 104 105 /** 106 * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream. 107 * <p> 108 * This method is useful where, 109 * </p> 110 * <ul> 111 * <li>Source InputStream is slow.</li> 112 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 113 * <li>It has network timeout associated.</li> 114 * </ul> 115 * <p> 116 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[]. 117 * </p> 118 * <p> 119 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}. 120 * </p> 121 * 122 * @param input Stream to be fully buffered. 123 * @return A fully buffered stream. 124 * @throws IOException if an I/O error occurs. 125 */ 126 public static InputStream toBufferedInputStream(final InputStream input) throws IOException { 127 return toBufferedInputStream(input, DEFAULT_SIZE); 128 } 129 130 /** 131 * Fetches entire contents of an {@link InputStream} and represent same data as result InputStream. 132 * <p> 133 * This method is useful where, 134 * </p> 135 * <ul> 136 * <li>Source InputStream is slow.</li> 137 * <li>It has network resources associated, so we cannot keep it open for long time.</li> 138 * <li>It has network timeout associated.</li> 139 * </ul> 140 * <p> 141 * It can be used in favor of {@link #toByteArray()}, since it avoids unnecessary allocation and copy of byte[]. 142 * </p> 143 * <p> 144 * This method buffers the input internally, so there is no need to use a {@link BufferedInputStream}. 145 * </p> 146 * 147 * @param input Stream to be fully buffered. 148 * @param size the initial buffer size. 149 * @return A fully buffered stream. 150 * @throws IOException if an I/O error occurs. 151 */ 152 public static InputStream toBufferedInputStream(final InputStream input, final int size) throws IOException { 153 // It does not matter if a ByteArrayOutputStream is not closed as close() is a no-op 154 try (UnsynchronizedByteArrayOutputStream output = builder().setBufferSize(size).get()) { 155 output.write(input); 156 return output.toInputStream(); 157 } 158 } 159 160 /** 161 * Constructs a new byte array output stream. The buffer capacity is initially. 162 * 163 * {@value AbstractByteArrayOutputStream#DEFAULT_SIZE} bytes, though its size increases if necessary. 164 * 165 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. 166 */ 167 @Deprecated 168 public UnsynchronizedByteArrayOutputStream() { 169 this(DEFAULT_SIZE); 170 } 171 172 private UnsynchronizedByteArrayOutputStream(final Builder builder) { 173 this(builder.getBufferSize()); 174 } 175 176 /** 177 * Constructs a new byte array output stream, with a buffer capacity of the specified size, in bytes. 178 * 179 * @param size the initial size. 180 * @throws IllegalArgumentException if size is negative. 181 * @deprecated Use {@link #builder()}, {@link Builder}, and {@link Builder#get()}. Will be private in 3.0.0. 182 */ 183 @Deprecated 184 public UnsynchronizedByteArrayOutputStream(final int size) { 185 if (size < 0) { 186 throw new IllegalArgumentException("Negative initial size: " + size); 187 } 188 needNewBuffer(size); 189 } 190 191 /** 192 * @see java.io.ByteArrayOutputStream#reset() 193 */ 194 @Override 195 public void reset() { 196 resetImpl(); 197 } 198 199 @Override 200 public int size() { 201 return count; 202 } 203 204 @Override 205 public byte[] toByteArray() { 206 return toByteArrayImpl(); 207 } 208 209 @Override 210 public InputStream toInputStream() { 211 // @formatter:off 212 return toInputStream((buffer, offset, length) -> Uncheck 213 .get(() -> UnsynchronizedByteArrayInputStream.builder() 214 .setByteArray(buffer) 215 .setOffset(offset) 216 .setLength(length) 217 .get())); 218 // @formatter:on 219 } 220 221 @Override 222 public void write(final byte[] b, final int off, final int len) { 223 IOUtils.checkFromIndexSize(b, off, len); 224 if (len == 0) { 225 return; 226 } 227 writeImpl(b, off, len); 228 } 229 230 @Override 231 public int write(final InputStream in) throws IOException { 232 return writeImpl(in); 233 } 234 235 @Override 236 public void write(final int b) { 237 writeImpl(b); 238 } 239 240 @Override 241 public void writeTo(final OutputStream out) throws IOException { 242 writeToImpl(out); 243 } 244}