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