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     * @param input the byte array to read from
121     * @param output the {@link OutputStream} to write to
122     * @throws IOException In case of an I/O problem
123     */
124    public static void copy(final byte[] input, final OutputStream output) throws IOException {
125        output.write(input);
126    }
127
128    /**
129     * Copies and convert bytes from a {@code byte[]} to chars on a
130     * {@link Writer}.
131     * The platform's default encoding is used for the byte-to-char conversion.
132     *
133     * @param input the byte array to read from
134     * @param output the {@link Writer} to write to
135     * @throws IOException In case of an I/O problem
136     * @deprecated Use {@link #copy(byte[], Writer, String)} instead
137     */
138    @Deprecated
139    public static void copy(final byte[] input, final Writer output) throws IOException {
140        final ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
141        copy(inputStream, output);
142    }
143
144    /**
145     * Copies and convert bytes from a {@code byte[]} to chars on a
146     * {@link Writer}, using the specified encoding.
147     *
148     * @param input the byte array to read from
149     * @param output the {@link Writer} to write to
150     * @param encoding The name of a supported character encoding. See the
151     * <a href="https://www.iana.org/assignments/character-sets">IANA
152     * Charset Registry</a> for a list of valid encoding types.
153     * @throws IOException In case of an I/O problem
154     */
155    public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException {
156        final ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
157        copy(inputStream, output, encoding);
158    }
159
160    /**
161     * Copies bytes from an {@link InputStream} to an
162     * {@link OutputStream}.
163     *
164     * @param input the {@link InputStream} to read from
165     * @param output the {@link OutputStream} to write to
166     * @return the number of bytes copied
167     * @throws IOException In case of an I/O problem
168     */
169    public static int copy(final InputStream input, final OutputStream output) throws IOException {
170        final byte[] buffer = IOUtils.byteArray();
171        int count = 0;
172        int n;
173        while (EOF != (n = input.read(buffer))) {
174            output.write(buffer, 0, n);
175            count += n;
176        }
177        return count;
178    }
179
180    /**
181     * Copies and convert bytes from an {@link InputStream} to chars on a
182     * {@link Writer}.
183     * <p>
184     * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
185     * </p>
186     *
187     * @param input the {@link InputStream} to read from
188     * @param output the {@link Writer} to write to
189     * @throws IOException In case of an I/O problem
190     * @deprecated Use {@link #copy(InputStream, Writer, String)} instead
191     */
192    @Deprecated
193    public static void copy(
194            final InputStream input,
195            final Writer output)
196                throws IOException {
197        // make explicit the dependency on the default encoding
198        final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset());
199        copy(in, output);
200    }
201
202    /**
203     * Copies and convert bytes from an {@link InputStream} to chars on a
204     * {@link Writer}, using the specified encoding.
205     *
206     * @param input the {@link InputStream} to read from
207     * @param output the {@link Writer} to write to
208     * @param encoding The name of a supported character encoding. See the
209     * <a href="https://www.iana.org/assignments/character-sets">IANA
210     * Charset Registry</a> for a list of valid encoding types.
211     * @throws IOException In case of an I/O problem
212     */
213    public static void copy(
214            final InputStream input,
215            final Writer output,
216            final String encoding)
217                throws IOException {
218        final InputStreamReader in = new InputStreamReader(input, encoding);
219        copy(in, output);
220    }
221
222    /**
223     * Serialize chars from a {@link Reader} to bytes on an
224     * {@link OutputStream}, and flush the {@link OutputStream}.
225     * <p>
226     * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
227     * </p>
228     *
229     * @param input the {@link Reader} to read from
230     * @param output the {@link OutputStream} to write to
231     * @throws IOException In case of an I/O problem
232     * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead
233     */
234    @Deprecated
235    public static void copy(
236            final Reader input,
237            final OutputStream output)
238                throws IOException {
239        // make explicit the dependency on the default encoding
240        final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset());
241        copy(input, out);
242        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
243        // have to flush here.
244        out.flush();
245    }
246
247    /**
248     * Serialize chars from a {@link Reader} to bytes on an
249     * {@link OutputStream}, and flush the {@link OutputStream}.
250     *
251     * @param input the {@link Reader} to read from
252     * @param output the {@link OutputStream} to write to
253     * @param encoding The name of a supported character encoding. See the
254     * <a href="https://www.iana.org/assignments/character-sets">IANA
255     * Charset Registry</a> for a list of valid encoding types.
256     * @throws IOException In case of an I/O problem
257     * @since 2.5
258     */
259    public static void copy(
260            final Reader input,
261            final OutputStream output,
262            final String encoding)
263                throws IOException {
264        final OutputStreamWriter out = new OutputStreamWriter(output, encoding);
265        copy(input, out);
266        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
267        // have to flush here.
268        out.flush();
269    }
270
271    /**
272     * Copies chars from a {@link Reader} to a {@link Writer}.
273     *
274     * @param input the {@link Reader} to read from
275     * @param output the {@link Writer} to write to
276     * @return the number of characters copied
277     * @throws IOException In case of an I/O problem
278     */
279    public static int copy(
280            final Reader input,
281            final Writer output)
282                throws IOException {
283        try (ScratchChars scratch = IOUtils.ScratchChars.get()) {
284            final char[] buffer = scratch.array();
285            int count = 0;
286            int n;
287            while (EOF != (n = input.read(buffer))) {
288                output.write(buffer, 0, n);
289                count += n;
290            }
291            return count;
292        }
293    }
294
295    /**
296     * Serialize chars from a {@link String} to bytes on an
297     * {@link OutputStream}, and
298     * flush the {@link OutputStream}.
299     * <p>
300     * This method uses the virtual machine's {@linkplain Charset#defaultCharset() default charset} for byte-to-char conversion.
301     * </p>
302     *
303     * @param input the {@link String} to read from
304     * @param output the {@link OutputStream} to write to
305     * @throws IOException In case of an I/O problem
306     * @deprecated Use {@link #copy(String, OutputStream, String)} instead
307     */
308    @Deprecated
309    public static void copy(
310            final String input,
311            final OutputStream output)
312                throws IOException {
313        final StringReader in = new StringReader(input);
314        // make explicit the dependency on the default encoding
315        final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset());
316        copy(in, out);
317        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
318        // have to flush here.
319        out.flush();
320    }
321
322    /**
323     * Serialize chars from a {@link String} to bytes on an
324     * {@link OutputStream}, and
325     * flush the {@link OutputStream}.
326     *
327     * @param input the {@link String} to read from
328     * @param output the {@link OutputStream} to write to
329     * @param encoding The name of a supported character encoding. See the
330     * <a href="https://www.iana.org/assignments/character-sets">IANA
331     * Charset Registry</a> for a list of valid encoding types.
332     * @throws IOException In case of an I/O problem
333     * @since 2.5
334     */
335    public static void copy(
336            final String input,
337            final OutputStream output,
338            final String encoding)
339                throws IOException {
340        final StringReader in = new StringReader(input);
341        final OutputStreamWriter out = new OutputStreamWriter(output, encoding);
342        copy(in, out);
343        // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
344        // have to flush here.
345        out.flush();
346    }
347
348    /**
349     * Copies chars from a {@link String} to a {@link Writer}.
350     *
351     * @param input the {@link String} to read from
352     * @param output the {@link Writer} to write to
353     * @throws IOException In case of an I/O problem
354     */
355    public static void copy(final String input, final Writer output)
356                throws IOException {
357        output.write(input);
358    }
359
360    /**
361     * Instances should NOT be constructed in standard programming.
362     *
363     * @deprecated TODO Make private in 3.0.
364     */
365    @Deprecated
366    public CopyUtils() {
367        // empty
368    }
369
370}