CopyUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.io;

  18. import static org.apache.commons.io.IOUtils.EOF;

  19. import java.io.ByteArrayInputStream;
  20. import java.io.IOException;
  21. import java.io.InputStream;
  22. import java.io.InputStreamReader;
  23. import java.io.OutputStream;
  24. import java.io.OutputStreamWriter;
  25. import java.io.Reader;
  26. import java.io.StringReader;
  27. import java.io.Writer;
  28. import java.nio.charset.Charset;

  29. /**
  30.  * This class provides static utility methods for buffered
  31.  * copying between sources ({@link InputStream}, {@link Reader},
  32.  * {@link String} and {@code byte[]}) and destinations
  33.  * ({@link OutputStream}, {@link Writer}, {@link String} and
  34.  * {@code byte[]}).
  35.  * <p>
  36.  * Unless otherwise noted, these {@code copy} methods do <em>not</em>
  37.  * flush or close the streams. Often doing so would require making non-portable
  38.  * assumptions about the streams' origin and further use. This means that both
  39.  * streams' {@code close()} methods must be called after copying. if one
  40.  * omits this step, then the stream resources (sockets, file descriptors) are
  41.  * released when the associated Stream is garbage-collected. It is not a good
  42.  * idea to rely on this mechanism. For a good overview of the distinction
  43.  * between "memory management" and "resource management", see
  44.  * <a href="http://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this
  45.  * UnixReview article</a>.
  46.  * <p>
  47.  * For byte-to-char methods, a {@code copy} variant allows the encoding
  48.  * to be selected (otherwise the platform default is used). We would like to
  49.  * encourage you to always specify the encoding because relying on the platform
  50.  * default can lead to unexpected results.
  51.  * <p>
  52.  * We don't provide special variants for the {@code copy} methods that
  53.  * let you specify the buffer size because in modern VMs the impact on speed
  54.  * seems to be minimal. We're using a default buffer size of 4 KB.
  55.  * <p>
  56.  * The {@code copy} methods use an internal buffer when copying. It is
  57.  * therefore advisable <em>not</em> to deliberately wrap the stream arguments
  58.  * to the {@code copy} methods in {@code Buffered*} streams. For
  59.  * example, don't do the following:
  60.  * <pre>
  61.  *  copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );
  62.  *  </pre>
  63.  * The rationale is as follows:
  64.  * <p>
  65.  * Imagine that an InputStream's read() is a very expensive operation, which
  66.  * would usually suggest wrapping in a BufferedInputStream. The
  67.  * BufferedInputStream works by issuing infrequent
  68.  * {@link InputStream#read(byte[] b, int off, int len)} requests on the
  69.  * underlying InputStream, to fill an internal buffer, from which further
  70.  * {@code read} requests can inexpensively get their data (until the buffer
  71.  * runs out).
  72.  * <p>
  73.  * However, the {@code copy} methods do the same thing, keeping an
  74.  * internal buffer, populated by
  75.  * {@link InputStream#read(byte[] b, int off, int len)} requests. Having two
  76.  * buffers (or three if the destination stream is also buffered) is pointless,
  77.  * and the unnecessary buffer management hurts performance slightly (about 3%,
  78.  * according to some simple experiments).
  79.  * <p>
  80.  * Behold, intrepid explorers; a map of this class:
  81.  * <pre>
  82.  *       Method      Input               Output          Dependency
  83.  *       ------      -----               ------          -------
  84.  * 1     copy        InputStream         OutputStream    (primitive)
  85.  * 2     copy        Reader              Writer          (primitive)
  86.  *
  87.  * 3     copy        InputStream         Writer          2
  88.  *
  89.  * 4     copy        Reader              OutputStream    2
  90.  *
  91.  * 5     copy        String              OutputStream    2
  92.  * 6     copy        String              Writer          (trivial)
  93.  *
  94.  * 7     copy        byte[]              Writer          3
  95.  * 8     copy        byte[]              OutputStream    (trivial)
  96.  * </pre>
  97.  * <p>
  98.  * Note that only the first two methods shuffle bytes; the rest use these
  99.  * two, or (if possible) copy using native Java copy methods. As there are
  100.  * method variants to specify the encoding, each row may
  101.  * correspond to up to 2 methods.
  102.  * <p>
  103.  * Provenance: Excalibur.
  104.  *
  105.  * @deprecated Use IOUtils. Will be removed in 3.0.
  106.  *  Methods renamed to IOUtils.write() or IOUtils.copy().
  107.  *  Null handling behavior changed in IOUtils (null data does not
  108.  *  throw NullPointerException).
  109.  */
  110. @Deprecated
  111. public class CopyUtils {

  112.     /**
  113.      * Copies bytes from a {@code byte[]} to an {@link OutputStream}.
  114.      * @param input the byte array to read from
  115.      * @param output the {@link OutputStream} to write to
  116.      * @throws IOException In case of an I/O problem
  117.      */
  118.     public static void copy(final byte[] input, final OutputStream output) throws IOException {
  119.         output.write(input);
  120.     }

  121.     /**
  122.      * Copies and convert bytes from a {@code byte[]} to chars on a
  123.      * {@link Writer}.
  124.      * The platform's default encoding is used for the byte-to-char conversion.
  125.      *
  126.      * @param input the byte array to read from
  127.      * @param output the {@link Writer} to write to
  128.      * @throws IOException In case of an I/O problem
  129.      * @deprecated Use {@link #copy(byte[], Writer, String)} instead
  130.      */
  131.     @Deprecated
  132.     public static void copy(final byte[] input, final Writer output) throws IOException {
  133.         final ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
  134.         copy(inputStream, output);
  135.     }

  136.     /**
  137.      * Copies and convert bytes from a {@code byte[]} to chars on a
  138.      * {@link Writer}, using the specified encoding.
  139.      *
  140.      * @param input the byte array to read from
  141.      * @param output the {@link Writer} to write to
  142.      * @param encoding The name of a supported character encoding. See the
  143.      * <a href="http://www.iana.org/assignments/character-sets">IANA
  144.      * Charset Registry</a> for a list of valid encoding types.
  145.      * @throws IOException In case of an I/O problem
  146.      */
  147.     public static void copy(final byte[] input, final Writer output, final String encoding) throws IOException {
  148.         final ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
  149.         copy(inputStream, output, encoding);
  150.     }

  151.     /**
  152.      * Copies bytes from an {@link InputStream} to an
  153.      * {@link OutputStream}.
  154.      *
  155.      * @param input the {@link InputStream} to read from
  156.      * @param output the {@link OutputStream} to write to
  157.      * @return the number of bytes copied
  158.      * @throws IOException In case of an I/O problem
  159.      */
  160.     public static int copy(final InputStream input, final OutputStream output) throws IOException {
  161.         final byte[] buffer = IOUtils.byteArray();
  162.         int count = 0;
  163.         int n;
  164.         while (EOF != (n = input.read(buffer))) {
  165.             output.write(buffer, 0, n);
  166.             count += n;
  167.         }
  168.         return count;
  169.     }

  170.     /**
  171.      * Copies and convert bytes from an {@link InputStream} to chars on a
  172.      * {@link Writer}.
  173.      * <p>
  174.      * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
  175.      * </p>
  176.      *
  177.      * @param input the {@link InputStream} to read from
  178.      * @param output the {@link Writer} to write to
  179.      * @throws IOException In case of an I/O problem
  180.      * @deprecated Use {@link #copy(InputStream, Writer, String)} instead
  181.      */
  182.     @Deprecated
  183.     public static void copy(
  184.             final InputStream input,
  185.             final Writer output)
  186.                 throws IOException {
  187.         // make explicit the dependency on the default encoding
  188.         final InputStreamReader in = new InputStreamReader(input, Charset.defaultCharset());
  189.         copy(in, output);
  190.     }

  191.     /**
  192.      * Copies and convert bytes from an {@link InputStream} to chars on a
  193.      * {@link Writer}, using the specified encoding.
  194.      *
  195.      * @param input the {@link InputStream} to read from
  196.      * @param output the {@link Writer} to write to
  197.      * @param encoding The name of a supported character encoding. See the
  198.      * <a href="http://www.iana.org/assignments/character-sets">IANA
  199.      * Charset Registry</a> for a list of valid encoding types.
  200.      * @throws IOException In case of an I/O problem
  201.      */
  202.     public static void copy(
  203.             final InputStream input,
  204.             final Writer output,
  205.             final String encoding)
  206.                 throws IOException {
  207.         final InputStreamReader in = new InputStreamReader(input, encoding);
  208.         copy(in, output);
  209.     }

  210.     /**
  211.      * Serialize chars from a {@link Reader} to bytes on an
  212.      * {@link OutputStream}, and flush the {@link OutputStream}.
  213.      * <p>
  214.      * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
  215.      * </p>
  216.      *
  217.      * @param input the {@link Reader} to read from
  218.      * @param output the {@link OutputStream} to write to
  219.      * @throws IOException In case of an I/O problem
  220.      * @deprecated Use {@link #copy(Reader, OutputStream, String)} instead
  221.      */
  222.     @Deprecated
  223.     public static void copy(
  224.             final Reader input,
  225.             final OutputStream output)
  226.                 throws IOException {
  227.         // make explicit the dependency on the default encoding
  228.         final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset());
  229.         copy(input, out);
  230.         // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
  231.         // have to flush here.
  232.         out.flush();
  233.     }

  234.     /**
  235.      * Serialize chars from a {@link Reader} to bytes on an
  236.      * {@link OutputStream}, and flush the {@link OutputStream}.
  237.      *
  238.      * @param input the {@link Reader} to read from
  239.      * @param output the {@link OutputStream} to write to
  240.      * @param encoding The name of a supported character encoding. See the
  241.      * <a href="http://www.iana.org/assignments/character-sets">IANA
  242.      * Charset Registry</a> for a list of valid encoding types.
  243.      * @throws IOException In case of an I/O problem
  244.      * @since 2.5
  245.      */
  246.     public static void copy(
  247.             final Reader input,
  248.             final OutputStream output,
  249.             final String encoding)
  250.                 throws IOException {
  251.         final OutputStreamWriter out = new OutputStreamWriter(output, encoding);
  252.         copy(input, out);
  253.         // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
  254.         // have to flush here.
  255.         out.flush();
  256.     }

  257.     /**
  258.      * Copies chars from a {@link Reader} to a {@link Writer}.
  259.      *
  260.      * @param input the {@link Reader} to read from
  261.      * @param output the {@link Writer} to write to
  262.      * @return the number of characters copied
  263.      * @throws IOException In case of an I/O problem
  264.      */
  265.     public static int copy(
  266.             final Reader input,
  267.             final Writer output)
  268.                 throws IOException {
  269.         final char[] buffer = IOUtils.getScratchCharArray();
  270.         int count = 0;
  271.         int n;
  272.         while (EOF != (n = input.read(buffer))) {
  273.             output.write(buffer, 0, n);
  274.             count += n;
  275.         }
  276.         return count;
  277.     }

  278.     /**
  279.      * Serialize chars from a {@link String} to bytes on an
  280.      * {@link OutputStream}, and
  281.      * flush the {@link OutputStream}.
  282.      * <p>
  283.      * This method uses the virtual machine's {@link Charset#defaultCharset() default charset} for byte-to-char conversion.
  284.      * </p>
  285.      *
  286.      * @param input the {@link String} to read from
  287.      * @param output the {@link OutputStream} to write to
  288.      * @throws IOException In case of an I/O problem
  289.      * @deprecated Use {@link #copy(String, OutputStream, String)} instead
  290.      */
  291.     @Deprecated
  292.     public static void copy(
  293.             final String input,
  294.             final OutputStream output)
  295.                 throws IOException {
  296.         final StringReader in = new StringReader(input);
  297.         // make explicit the dependency on the default encoding
  298.         final OutputStreamWriter out = new OutputStreamWriter(output, Charset.defaultCharset());
  299.         copy(in, out);
  300.         // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
  301.         // have to flush here.
  302.         out.flush();
  303.     }

  304.     /**
  305.      * Serialize chars from a {@link String} to bytes on an
  306.      * {@link OutputStream}, and
  307.      * flush the {@link OutputStream}.
  308.      *
  309.      * @param input the {@link String} to read from
  310.      * @param output the {@link OutputStream} to write to
  311.      * @param encoding The name of a supported character encoding. See the
  312.      * <a href="http://www.iana.org/assignments/character-sets">IANA
  313.      * Charset Registry</a> for a list of valid encoding types.
  314.      * @throws IOException In case of an I/O problem
  315.      * @since 2.5
  316.      */
  317.     public static void copy(
  318.             final String input,
  319.             final OutputStream output,
  320.             final String encoding)
  321.                 throws IOException {
  322.         final StringReader in = new StringReader(input);
  323.         final OutputStreamWriter out = new OutputStreamWriter(output, encoding);
  324.         copy(in, out);
  325.         // XXX Unless anyone is planning on rewriting OutputStreamWriter, we
  326.         // have to flush here.
  327.         out.flush();
  328.     }

  329.     /**
  330.      * Copies chars from a {@link String} to a {@link Writer}.
  331.      *
  332.      * @param input the {@link String} to read from
  333.      * @param output the {@link Writer} to write to
  334.      * @throws IOException In case of an I/O problem
  335.      */
  336.     public static void copy(final String input, final Writer output)
  337.                 throws IOException {
  338.         output.write(input);
  339.     }

  340.     /**
  341.      * Instances should NOT be constructed in standard programming.
  342.      *
  343.      * @deprecated TODO Make private in 3.0.
  344.      */
  345.     @Deprecated
  346.     public CopyUtils() {
  347.         // empty
  348.     }

  349. }