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