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