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