    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
    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}