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}