View Javadoc
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 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      * <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 }