    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}