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