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; 018 019import static org.apache.commons.io.IOUtils.EOF; 020 021import java.io.ByteArrayInputStream; 022import java.io.IOException; 023import java.io.InputStream; 024import java.io.InputStreamReader; 025import java.io.OutputStream; 026import java.io.OutputStreamWriter; 027import java.io.Reader; 028import java.io.StringReader; 029import java.io.Writer; 030import java.nio.charset.Charset; 031 032import org.apache.commons.io.IOUtils.ScratchChars; 033 034/** 035 * This class provides static utility methods for buffered 036 * copying between sources ({@link InputStream}, {@link Reader}, 037 * {@link String} and {@code byte[]}) and destinations 038 * ({@link OutputStream}, {@link Writer}, {@link String} and 039 * {@code byte[]}). 040 * <p> 041 * Unless otherwise noted, these {@code copy} methods do <em>not</em> 042 * flush or close the streams. Often doing so would require making non-portable 043 * assumptions about the streams' origin and further use. This means that both 044 * streams' {@code close()} methods must be called after copying. if one 045 * omits this step, then the stream resources (sockets, file descriptors) are 046 * released when the associated Stream is garbage-collected. It is not a good 047 * idea to rely on this mechanism. For a good overview of the distinction 048 * between "memory management" and "resource management", see 049 * <a href="https://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this 050 * UnixReview article</a>. 051 * <p> 052 * For byte-to-char methods, a {@code copy} variant allows the encoding 053 * to be selected (otherwise the platform default is used). We would like to 054 * encourage you to always specify the encoding because relying on the platform 055 * default can lead to unexpected results. 056 * <p> 057 * We don't provide special variants for the {@code copy} methods that 058 * let you specify the buffer size because in modern VMs the impact on speed 059 * seems to be minimal. We're using a default buffer size of 4 KB. 060 * <p> 061 * The {@code copy} methods use an internal buffer when copying. It is 062 * therefore advisable <em>not</em> to deliberately wrap the stream arguments 063 * to the {@code copy} methods in {@code Buffered*} streams. For 064 * example, don't do the following: 065 * <pre> 066 * copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) ); 067 * </pre> 068 * The rationale is as follows: 069 * <p> 070 * Imagine that an InputStream's read() is a very expensive operation, which 071 * would usually suggest wrapping in a BufferedInputStream. The 072 * BufferedInputStream works by issuing infrequent 073 * {@link InputStream#read(byte[] b, int off, int len)} requests on the 074 * underlying InputStream, to fill an internal buffer, from which further 075 * {@code read} requests can inexpensively get their data (until the buffer 076 * runs out). 077 * <p> 078 * However, the {@code copy} methods do the same thing, keeping an 079 * internal buffer, populated by 080 * {@link InputStream#read(byte[] b, int off, int len)} requests. Having two 081 * buffers (or three if the destination stream is also buffered) is pointless, 082 * and the unnecessary buffer management hurts performance slightly (about 3%, 083 * according to some simple experiments). 084 * <p> 085 * Behold, intrepid explorers; a map of this class: 086 * <pre> 087 * Method Input Output Dependency 088 * ------ ----- ------ ------- 089 * 1 copy InputStream OutputStream (primitive) 090 * 2 copy Reader Writer (primitive) 091 * 092 * 3 copy InputStream Writer 2 093 * 094 * 4 copy Reader OutputStream 2 095 * 096 * 5 copy String OutputStream 2 097 * 6 copy String Writer (trivial) 098 * 099 * 7 copy byte[] Writer 3 100 * 8 copy byte[] OutputStream (trivial) 101 * </pre> 102 * <p> 103 * Note that only the first two methods shuffle bytes; the rest use these 104 * two, or (if possible) copy using native Java copy methods. As there are 105 * method variants to specify the encoding, each row may 106 * correspond to up to 2 methods. 107 * <p> 108 * Provenance: Excalibur. 109 * 110 * @deprecated Use IOUtils. Will be removed in 3.0. 111 * Methods renamed to IOUtils.write() or IOUtils.copy(). 112 * Null handling behavior changed in IOUtils (null data does not 113 * throw NullPointerException). 114 */ 115@Deprecated 116public class CopyUtils { 117 118 /** 119 * Copies bytes from a {@code byte[]} to an {@link OutputStream}. 120 * 121 * @param input the byte array to read from. 122 * @param output the {@link OutputStream} to write to. 123 * @throws IOException In case of an I/O problem. 124 */ 125 public static void copy(final byte[] input, final OutputStream output) throws IOException { 126 output.write(input); 127 } 128 129 /** 130 * Copies and convert bytes from a {@code byte[]} to chars on a 131 * {@link Writer}. 132 * The platform's default encoding is used for the byte-to-char conversion. 133 * 134 * @param input the byte array to read from. 135 * @param output the {@link Writer} to write to. 136 * @throws IOException In case of an I/O problem. 137 * @deprecated Use {@link #copy(byte[], Writer, String)} instead. 138 */ 139 @Deprecated 140 public static void copy(final byte[] input, final Writer output) throws IOException { 141 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 142 copy(inputStream, output); 143 } 144 145 /** 146 * Copies and convert bytes from a {@code byte[]} to chars on a 147 * {@link Writer}, using the specified encoding. 148 * 149 * @param input the byte array to read from. 150 * @param output the {@link Writer} to write to. 151 * @param encoding The name of a supported character encoding. See the 152 * <a href="https://www.iana.org/assignments/character-sets">IANA 153 * Charset Registry</a> for a list of valid encoding types. 154 * @throws IOException In case of an I/O problem. 155 */ 156 public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException { 157 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 158 copy(inputStream, output, encoding); 159 } 160 161 /** 162 * Copies bytes from an {@link InputStream} to an 163 * {@link OutputStream}. 164 * 165 * @param input the {@link InputStream} to read from. 166 * @param output the {@link OutputStream} to write to. 167 * @return the number of bytes copied. 168 * @throws IOException In case of an I/O problem. 169 */ 170 public static int copy(final InputStream input, final OutputStream output) throws IOException { 171 final byte[] buffer = IOUtils.byteArray(); 172 int count = 0; 173 int n; 174 while (EOF != (n = input.read(buffer))) { 175 output.write(buffer, 0, n); 176 count += n; 177 } 178 return count; 179 } 180 181 /** 182 * Copies and convert bytes from an {@link InputStream} to chars on a 183 * {@link Writer}. 184 * <p> 185 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 186 * </p> 187 * 188 * @param input the {@link InputStream} to read from. 189 * @param output the {@link Writer} to write to. 190 * @throws IOException In case of an I/O problem. 191 * @deprecated Use {@link #copy(InputStream, Writer, String)} instead. 192 */ 193 @Deprecated 194 public static void copy( 195 final InputStream input, 196 final Writer output) 197 throws IOException { 198 // make explicit the dependency on the default encoding 199 final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset()); 200 copy(in, output); 201 } 202 203 /** 204 * Copies and convert bytes from an {@link InputStream} to chars on a 205 * {@link Writer}, using the specified encoding. 206 * 207 * @param input the {@link InputStream} to read from. 208 * @param output the {@link Writer} to write to. 209 * @param encoding The name of a supported character encoding. See the 210 * <a href="https://www.iana.org/assignments/character-sets">IANA 211 * Charset Registry</a> for a list of valid encoding types. 212 * @throws IOException In case of an I/O problem. 213 */ 214 public static void copy( 215 final InputStream input, 216 final Writer output, 217 final String encoding) 218 throws IOException { 219 final InputStreamReader in = new InputStreamReader(input, encoding); 220 copy(in, output); 221 } 222 223 /** 224 * Serialize chars from a {@link Reader} to bytes on an 225 * {@link OutputStream}, and flush the {@link OutputStream}. 226 * <p> 227 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 228 * </p> 229 * 230 * @param input the {@link Reader} to read from. 231 * @param output the {@link OutputStream} to write to. 232 * @throws IOException In case of an I/O problem. 233 * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead. 234 */ 235 @Deprecated 236 public static void copy( 237 final Reader input, 238 final OutputStream output) 239 throws IOException { 240 // make explicit the dependency on the default encoding 241 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 242 copy(input, out); 243 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 244 // have to flush here. 245 out.flush(); 246 } 247 248 /** 249 * Serialize chars from a {@link Reader} to bytes on an 250 * {@link OutputStream}, and flush the {@link OutputStream}. 251 * 252 * @param input the {@link Reader} to read from. 253 * @param output the {@link OutputStream} to write to. 254 * @param encoding The name of a supported character encoding. See the 255 * <a href="https://www.iana.org/assignments/character-sets">IANA 256 * Charset Registry</a> for a list of valid encoding types. 257 * @throws IOException In case of an I/O problem. 258 * @since 2.5 259 */ 260 public static void copy( 261 final Reader input, 262 final OutputStream output, 263 final String encoding) 264 throws IOException { 265 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 266 copy(input, out); 267 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 268 // have to flush here. 269 out.flush(); 270 } 271 272 /** 273 * Copies chars from a {@link Reader} to a {@link Writer}. 274 * 275 * @param input the {@link Reader} to read from. 276 * @param output the {@link Writer} to write to. 277 * @return the number of characters copied. 278 * @throws IOException In case of an I/O problem. 279 */ 280 public static int copy( 281 final Reader input, 282 final Writer output) 283 throws IOException { 284 try (ScratchChars scratch = IOUtils.ScratchChars.get()) { 285 final char[] buffer = scratch.array(); 286 int count = 0; 287 int n; 288 while (EOF != (n = input.read(buffer))) { 289 output.write(buffer, 0, n); 290 count += n; 291 } 292 return count; 293 } 294 } 295 296 /** 297 * Serialize chars from a {@link String} to bytes on an 298 * {@link OutputStream}, and 299 * flush the {@link OutputStream}. 300 * <p> 301 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 302 * </p> 303 * 304 * @param input the {@link String} to read from. 305 * @param output the {@link OutputStream} to write to. 306 * @throws IOException In case of an I/O problem. 307 * @deprecated Use {@link #copy(String, OutputStream, String)} instead. 308 */ 309 @Deprecated 310 public static void copy( 311 final String input, 312 final OutputStream output) 313 throws IOException { 314 final StringReader in = new StringReader(input); 315 // make explicit the dependency on the default encoding 316 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 317 copy(in, out); 318 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 319 // have to flush here. 320 out.flush(); 321 } 322 323 /** 324 * Serialize chars from a {@link String} to bytes on an 325 * {@link OutputStream}, and 326 * flush the {@link OutputStream}. 327 * 328 * @param input the {@link String} to read from. 329 * @param output the {@link OutputStream} to write to. 330 * @param encoding The name of a supported character encoding. See the 331 * <a href="https://www.iana.org/assignments/character-sets">IANA 332 * Charset Registry</a> for a list of valid encoding types. 333 * @throws IOException In case of an I/O problem. 334 * @since 2.5 335 */ 336 public static void copy( 337 final String input, 338 final OutputStream output, 339 final String encoding) 340 throws IOException { 341 final StringReader in = new StringReader(input); 342 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 343 copy(in, out); 344 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 345 // have to flush here. 346 out.flush(); 347 } 348 349 /** 350 * Copies chars from a {@link String} to a {@link Writer}. 351 * 352 * @param input the {@link String} to read from. 353 * @param output the {@link Writer} to write to. 354 * @throws IOException In case of an I/O problem. 355 */ 356 public static void copy(final String input, final Writer output) 357 throws IOException { 358 output.write(input); 359 } 360 361 /** 362 * Instances should NOT be constructed in standard programming. 363 * 364 * @deprecated TODO Make private in 3.0. 365 */ 366 @Deprecated 367 public CopyUtils() { 368 // empty 369 } 370 371}