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 * @param input the byte array to read from 121 * @param output the {@link OutputStream} to write to 122 * @throws IOException In case of an I/O problem 123 */ 124 public static void copy(final byte[] input, final OutputStream output) throws IOException { 125 output.write(input); 126 } 127 128 /** 129 * Copies and convert bytes from a {@code byte[]} to chars on a 130 * {@link Writer}. 131 * The platform's default encoding is used for the byte-to-char conversion. 132 * 133 * @param input the byte array to read from 134 * @param output the {@link Writer} to write to 135 * @throws IOException In case of an I/O problem 136 * @deprecated Use {@link #copy(byte[], Writer, String)} instead 137 */ 138 @Deprecated 139 public static void copy(final byte[] input, final Writer output) throws IOException { 140 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 141 copy(inputStream, output); 142 } 143 144 /** 145 * Copies and convert bytes from a {@code byte[]} to chars on a 146 * {@link Writer}, using the specified encoding. 147 * 148 * @param input the byte array to read from 149 * @param output the {@link Writer} to write to 150 * @param encoding The name of a supported character encoding. See the 151 * <a href="https://www.iana.org/assignments/character-sets">IANA 152 * Charset Registry</a> for a list of valid encoding types. 153 * @throws IOException In case of an I/O problem 154 */ 155 public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException { 156 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 157 copy(inputStream, output, encoding); 158 } 159 160 /** 161 * Copies bytes from an {@link InputStream} to an 162 * {@link OutputStream}. 163 * 164 * @param input the {@link InputStream} to read from 165 * @param output the {@link OutputStream} to write to 166 * @return the number of bytes copied 167 * @throws IOException In case of an I/O problem 168 */ 169 public static int copy(final InputStream input, final OutputStream output) throws IOException { 170 final byte[] buffer = IOUtils.byteArray(); 171 int count = 0; 172 int n; 173 while (EOF != (n = input.read(buffer))) { 174 output.write(buffer, 0, n); 175 count += n; 176 } 177 return count; 178 } 179 180 /** 181 * Copies and convert bytes from an {@link InputStream} to chars on a 182 * {@link Writer}. 183 * <p> 184 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 185 * </p> 186 * 187 * @param input the {@link InputStream} to read from 188 * @param output the {@link Writer} to write to 189 * @throws IOException In case of an I/O problem 190 * @deprecated Use {@link #copy(InputStream, Writer, String)} instead 191 */ 192 @Deprecated 193 public static void copy( 194 final InputStream input, 195 final Writer output) 196 throws IOException { 197 // make explicit the dependency on the default encoding 198 final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset()); 199 copy(in, output); 200 } 201 202 /** 203 * Copies and convert bytes from an {@link InputStream} to chars on a 204 * {@link Writer}, using the specified encoding. 205 * 206 * @param input the {@link InputStream} to read from 207 * @param output the {@link Writer} to write to 208 * @param encoding The name of a supported character encoding. See the 209 * <a href="https://www.iana.org/assignments/character-sets">IANA 210 * Charset Registry</a> for a list of valid encoding types. 211 * @throws IOException In case of an I/O problem 212 */ 213 public static void copy( 214 final InputStream input, 215 final Writer output, 216 final String encoding) 217 throws IOException { 218 final InputStreamReader in = new InputStreamReader(input, encoding); 219 copy(in, output); 220 } 221 222 /** 223 * Serialize chars from a {@link Reader} to bytes on an 224 * {@link OutputStream}, and flush the {@link OutputStream}. 225 * <p> 226 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 227 * </p> 228 * 229 * @param input the {@link Reader} to read from 230 * @param output the {@link OutputStream} to write to 231 * @throws IOException In case of an I/O problem 232 * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead 233 */ 234 @Deprecated 235 public static void copy( 236 final Reader input, 237 final OutputStream output) 238 throws IOException { 239 // make explicit the dependency on the default encoding 240 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 241 copy(input, out); 242 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 243 // have to flush here. 244 out.flush(); 245 } 246 247 /** 248 * Serialize chars from a {@link Reader} to bytes on an 249 * {@link OutputStream}, and flush the {@link OutputStream}. 250 * 251 * @param input the {@link Reader} to read from 252 * @param output the {@link OutputStream} to write to 253 * @param encoding The name of a supported character encoding. See the 254 * <a href="https://www.iana.org/assignments/character-sets">IANA 255 * Charset Registry</a> for a list of valid encoding types. 256 * @throws IOException In case of an I/O problem 257 * @since 2.5 258 */ 259 public static void copy( 260 final Reader input, 261 final OutputStream output, 262 final String encoding) 263 throws IOException { 264 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 265 copy(input, out); 266 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 267 // have to flush here. 268 out.flush(); 269 } 270 271 /** 272 * Copies chars from a {@link Reader} to a {@link Writer}. 273 * 274 * @param input the {@link Reader} to read from 275 * @param output the {@link Writer} to write to 276 * @return the number of characters copied 277 * @throws IOException In case of an I/O problem 278 */ 279 public static int copy( 280 final Reader input, 281 final Writer output) 282 throws IOException { 283 try (ScratchChars scratch = IOUtils.ScratchChars.get()) { 284 final char[] buffer = scratch.array(); 285 int count = 0; 286 int n; 287 while (EOF != (n = input.read(buffer))) { 288 output.write(buffer, 0, n); 289 count += n; 290 } 291 return count; 292 } 293 } 294 295 /** 296 * Serialize chars from a {@link String} to bytes on an 297 * {@link OutputStream}, and 298 * flush the {@link OutputStream}. 299 * <p> 300 * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion. 301 * </p> 302 * 303 * @param input the {@link String} to read from 304 * @param output the {@link OutputStream} to write to 305 * @throws IOException In case of an I/O problem 306 * @deprecated Use {@link #copy(String, OutputStream, String)} instead 307 */ 308 @Deprecated 309 public static void copy( 310 final String input, 311 final OutputStream output) 312 throws IOException { 313 final StringReader in = new StringReader(input); 314 // make explicit the dependency on the default encoding 315 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 316 copy(in, out); 317 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 318 // have to flush here. 319 out.flush(); 320 } 321 322 /** 323 * Serialize chars from a {@link String} to bytes on an 324 * {@link OutputStream}, and 325 * flush the {@link OutputStream}. 326 * 327 * @param input the {@link String} to read from 328 * @param output the {@link OutputStream} to write to 329 * @param encoding The name of a supported character encoding. See the 330 * <a href="https://www.iana.org/assignments/character-sets">IANA 331 * Charset Registry</a> for a list of valid encoding types. 332 * @throws IOException In case of an I/O problem 333 * @since 2.5 334 */ 335 public static void copy( 336 final String input, 337 final OutputStream output, 338 final String encoding) 339 throws IOException { 340 final StringReader in = new StringReader(input); 341 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 342 copy(in, out); 343 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 344 // have to flush here. 345 out.flush(); 346 } 347 348 /** 349 * Copies chars from a {@link String} to a {@link Writer}. 350 * 351 * @param input the {@link String} to read from 352 * @param output the {@link Writer} to write to 353 * @throws IOException In case of an I/O problem 354 */ 355 public static void copy(final String input, final Writer output) 356 throws IOException { 357 output.write(input); 358 } 359 360 /** 361 * Instances should NOT be constructed in standard programming. 362 * 363 * @deprecated TODO Make private in 3.0. 364 */ 365 @Deprecated 366 public CopyUtils() { 367 // empty 368 } 369 370}