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