1 /* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 package org.apache.commons.io; 18 19 import static org.apache.commons.io.IOUtils.EOF; 20 21 import java.io.ByteArrayInputStream; 22 import java.io.IOException; 23 import java.io.InputStream; 24 import java.io.InputStreamReader; 25 import java.io.OutputStream; 26 import java.io.OutputStreamWriter; 27 import java.io.Reader; 28 import java.io.StringReader; 29 import java.io.Writer; 30 import java.nio.charset.Charset; 31 32 /** 33 * This class provides static utility methods for buffered 34 * copying between sources ({@link InputStream}, {@link Reader}, 35 * {@link String} and {@code byte[]}) and destinations 36 * ({@link OutputStream}, {@link Writer}, {@link String} and 37 * {@code byte[]}). 38 * <p> 39 * Unless otherwise noted, these {@code copy} methods do <em>not</em> 40 * flush or close the streams. Often doing so would require making non-portable 41 * assumptions about the streams' origin and further use. This means that both 42 * streams' {@code close()} methods must be called after copying. if one 43 * omits this step, then the stream resources (sockets, file descriptors) are 44 * released when the associated Stream is garbage-collected. It is not a good 45 * idea to rely on this mechanism. For a good overview of the distinction 46 * between "memory management" and "resource management", see 47 * <a href="http://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this 48 * UnixReview article</a>. 49 * <p> 50 * For byte-to-char methods, a {@code copy} variant allows the encoding 51 * to be selected (otherwise the platform default is used). We would like to 52 * encourage you to always specify the encoding because relying on the platform 53 * default can lead to unexpected results. 54 * <p> 55 * We don't provide special variants for the {@code copy} methods that 56 * let you specify the buffer size because in modern VMs the impact on speed 57 * seems to be minimal. We're using a default buffer size of 4 KB. 58 * <p> 59 * The {@code copy} methods use an internal buffer when copying. It is 60 * therefore advisable <em>not</em> to deliberately wrap the stream arguments 61 * to the {@code copy} methods in {@code Buffered*} streams. For 62 * example, don't do the following: 63 * <pre> 64 * copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) ); 65 * </pre> 66 * The rationale is as follows: 67 * <p> 68 * Imagine that an InputStream's read() is a very expensive operation, which 69 * would usually suggest wrapping in a BufferedInputStream. The 70 * BufferedInputStream works by issuing infrequent 71 * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the 72 * underlying InputStream, to fill an internal buffer, from which further 73 * {@code read} requests can inexpensively get their data (until the buffer 74 * runs out). 75 * <p> 76 * However, the {@code copy} methods do the same thing, keeping an 77 * internal buffer, populated by 78 * {@link InputStream#read(byte[] b, int off, int len)} requests. Having two 79 * buffers (or three if the destination stream is also buffered) is pointless, 80 * and the unnecessary buffer management hurts performance slightly (about 3%, 81 * according to some simple experiments). 82 * <p> 83 * Behold, intrepid explorers; a map of this class: 84 * <pre> 85 * Method Input Output Dependency 86 * ------ ----- ------ ------- 87 * 1 copy InputStream OutputStream (primitive) 88 * 2 copy Reader Writer (primitive) 89 * 90 * 3 copy InputStream Writer 2 91 * 92 * 4 copy Reader OutputStream 2 93 * 94 * 5 copy String OutputStream 2 95 * 6 copy String Writer (trivial) 96 * 97 * 7 copy byte[] Writer 3 98 * 8 copy byte[] OutputStream (trivial) 99 * </pre> 100 * <p> 101 * Note that only the first two methods shuffle bytes; the rest use these 102 * two, or (if possible) copy using native Java copy methods. As there are 103 * method variants to specify the encoding, each row may 104 * correspond to up to 2 methods. 105 * <p> 106 * Provenance: Excalibur. 107 * 108 * @deprecated Use IOUtils. Will be removed in 3.0. 109 * Methods renamed to IOUtils.write() or IOUtils.copy(). 110 * Null handling behavior changed in IOUtils (null data does not 111 * throw NullPointerException). 112 */ 113 @Deprecated 114 public class CopyUtils { 115 116 /** 117 * Copies bytes from a {@code byte[]} to an {@link OutputStream}. 118 * @param input the byte array to read from 119 * @param output the {@link OutputStream} to write to 120 * @throws IOException In case of an I/O problem 121 */ 122 public static void copy(final byte[] input, final OutputStream output) throws IOException { 123 output.write(input); 124 } 125 126 /** 127 * Copies and convert bytes from a {@code byte[]} to chars on a 128 * {@link Writer}. 129 * The platform's default encoding is used for the byte-to-char conversion. 130 * 131 * @param input the byte array to read from 132 * @param output the {@link Writer} to write to 133 * @throws IOException In case of an I/O problem 134 * @deprecated Use {@link #copy(byte[], Writer, String)} instead 135 */ 136 @Deprecated 137 public static void copy(final byte[] input, final Writer output) throws IOException { 138 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 139 copy(inputStream, output); 140 } 141 142 /** 143 * Copies and convert bytes from a {@code byte[]} to chars on a 144 * {@link Writer}, using the specified encoding. 145 * 146 * @param input the byte array to read from 147 * @param output the {@link Writer} to write to 148 * @param encoding The name of a supported character encoding. See the 149 * <a href="http://www.iana.org/assignments/character-sets">IANA 150 * Charset Registry</a> for a list of valid encoding types. 151 * @throws IOException In case of an I/O problem 152 */ 153 public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException { 154 final ByteArrayInputStream inputStream = new ByteArrayInputStream(input); 155 copy(inputStream, output, encoding); 156 } 157 158 /** 159 * Copies bytes from an {@link InputStream} to an 160 * {@link OutputStream}. 161 * 162 * @param input the {@link InputStream} to read from 163 * @param output the {@link OutputStream} to write to 164 * @return the number of bytes copied 165 * @throws IOException In case of an I/O problem 166 */ 167 public static int copy(final InputStream input, final OutputStream output) throws IOException { 168 final byte[] buffer = IOUtils.byteArray(); 169 int count = 0; 170 int n; 171 while (EOF != (n = input.read(buffer))) { 172 output.write(buffer, 0, n); 173 count += n; 174 } 175 return count; 176 } 177 178 /** 179 * Copies and convert bytes from an {@link InputStream} to chars on a 180 * {@link Writer}. 181 * The platform's default encoding is used for the byte-to-char conversion. 182 * 183 * @param input the {@link InputStream} to read from 184 * @param output the {@link Writer} to write to 185 * @throws IOException In case of an I/O problem 186 * @deprecated Use {@link #copy(InputStream, Writer, String)} instead 187 */ 188 @Deprecated 189 public static void copy( 190 final InputStream input, 191 final Writer output) 192 throws IOException { 193 // make explicit the dependency on the default encoding 194 final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset()); 195 copy(in, output); 196 } 197 198 /** 199 * Copies and convert bytes from an {@link InputStream} to chars on a 200 * {@link Writer}, using the specified encoding. 201 * 202 * @param input the {@link InputStream} to read from 203 * @param output the {@link Writer} to write to 204 * @param encoding The name of a supported character encoding. See the 205 * <a href="http://www.iana.org/assignments/character-sets">IANA 206 * Charset Registry</a> for a list of valid encoding types. 207 * @throws IOException In case of an I/O problem 208 */ 209 public static void copy( 210 final InputStream input, 211 final Writer output, 212 final String encoding) 213 throws IOException { 214 final InputStreamReader in = new InputStreamReader(input, encoding); 215 copy(in, output); 216 } 217 218 /** 219 * Serialize chars from a {@link Reader} to bytes on an 220 * {@link OutputStream}, and flush the {@link OutputStream}. 221 * Uses the default platform encoding. 222 * 223 * @param input the {@link Reader} to read from 224 * @param output the {@link OutputStream} to write to 225 * @throws IOException In case of an I/O problem 226 * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead 227 */ 228 @Deprecated 229 public static void copy( 230 final Reader input, 231 final OutputStream output) 232 throws IOException { 233 // make explicit the dependency on the default encoding 234 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 235 copy(input, out); 236 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 237 // have to flush here. 238 out.flush(); 239 } 240 241 /** 242 * Serialize chars from a {@link Reader} to bytes on an 243 * {@link OutputStream}, and flush the {@link OutputStream}. 244 * 245 * @param input the {@link Reader} to read from 246 * @param output the {@link OutputStream} to write to 247 * @param encoding The name of a supported character encoding. See the 248 * <a href="http://www.iana.org/assignments/character-sets">IANA 249 * Charset Registry</a> for a list of valid encoding types. 250 * @throws IOException In case of an I/O problem 251 * @since 2.5 252 */ 253 public static void copy( 254 final Reader input, 255 final OutputStream output, 256 final String encoding) 257 throws IOException { 258 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 259 copy(input, out); 260 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 261 // have to flush here. 262 out.flush(); 263 } 264 265 /** 266 * Copies chars from a {@link Reader} to a {@link Writer}. 267 * 268 * @param input the {@link Reader} to read from 269 * @param output the {@link Writer} to write to 270 * @return the number of characters copied 271 * @throws IOException In case of an I/O problem 272 */ 273 public static int copy( 274 final Reader input, 275 final Writer output) 276 throws IOException { 277 final char[] buffer = IOUtils.getScratchCharArray(); 278 int count = 0; 279 int n; 280 while (EOF != (n = input.read(buffer))) { 281 output.write(buffer, 0, n); 282 count += n; 283 } 284 return count; 285 } 286 287 /** 288 * Serialize chars from a {@link String} to bytes on an 289 * {@link OutputStream}, and 290 * flush the {@link OutputStream}. 291 * Uses the platform default encoding. 292 * 293 * @param input the {@link String} to read from 294 * @param output the {@link OutputStream} to write to 295 * @throws IOException In case of an I/O problem 296 * @deprecated Use {@link #copy(String, OutputStream, String)} instead 297 */ 298 @Deprecated 299 public static void copy( 300 final String input, 301 final OutputStream output) 302 throws IOException { 303 final StringReader in = new StringReader(input); 304 // make explicit the dependency on the default encoding 305 final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset()); 306 copy(in, out); 307 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 308 // have to flush here. 309 out.flush(); 310 } 311 312 /** 313 * Serialize chars from a {@link String} to bytes on an 314 * {@link OutputStream}, and 315 * flush the {@link OutputStream}. 316 * 317 * @param input the {@link String} to read from 318 * @param output the {@link OutputStream} to write to 319 * @param encoding The name of a supported character encoding. See the 320 * <a href="http://www.iana.org/assignments/character-sets">IANA 321 * Charset Registry</a> for a list of valid encoding types. 322 * @throws IOException In case of an I/O problem 323 * @since 2.5 324 */ 325 public static void copy( 326 final String input, 327 final OutputStream output, 328 final String encoding) 329 throws IOException { 330 final StringReader in = new StringReader(input); 331 final OutputStreamWriter out = new OutputStreamWriter(output, encoding); 332 copy(in, out); 333 // XXX Unless anyone is planning on rewriting OutputStreamWriter, we 334 // have to flush here. 335 out.flush(); 336 } 337 338 /** 339 * Copies chars from a {@link String} to a {@link Writer}. 340 * 341 * @param input the {@link String} to read from 342 * @param output the {@link Writer} to write to 343 * @throws IOException In case of an I/O problem 344 */ 345 public static void copy(final String input, final Writer output) 346 throws IOException { 347 output.write(input); 348 } 349 350 /** 351 * Instances should NOT be constructed in standard programming. 352 * 353 * @deprecated TODO Make private in 3.0. 354 */ 355 @Deprecated 356 public CopyUtils() { 357 // empty 358 } 359 360 }