| /* |
| * Copyright 2001-2004 The Apache Software Foundation. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.commons.io; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.InputStreamReader; |
| import java.io.OutputStream; |
| import java.io.OutputStreamWriter; |
| import java.io.Reader; |
| import java.io.StringReader; |
| import java.io.Writer; |
| |
| /** |
| * <p> |
| * This class provides static utility methods for buffered |
| * copying between sources (<code>InputStream</code>, <code>Reader</code>, <code>String</code> and |
| * <code>byte[]</code>) and destinations (<code>OutputStream</code>, <code>Writer</code>, |
| * <code>String</code> and <code>byte[]</code>). |
| * </p> |
| * |
| * <p>Unless otherwise noted, these <code>copy</code> methods do <em>not</em> flush or close the |
| * streams. Often doing so would require making non-portable assumptions about the streams' origin |
| * and further use. This means that both streams' <code>close()</code> methods must be called after |
| * copying. if one omits this step, then the stream resources (sockets, file descriptors) are |
| * released when the associated Stream is garbage-collected. It is not a good idea to rely on this |
| * mechanism. For a good overview of the distinction between "memory management" and "resource |
| * management", see <a href="http://www.unixreview.com/articles/1998/9804/9804ja/ja.htm">this |
| * UnixReview article</a>.</p> |
| * |
| * <p>For byte-to-char methods, a <code>copy</code> variant allows the encoding |
| * to be selected (otherwise the platform default is used). We would like to |
| * encourage you to always specify the encoding because relying on the platform |
| * default can lead to unexpected results.</p> |
| * |
| * <p>We don't provide special variants for the <code>copy</code> methods that |
| * let you specify the buffer size because in modern VMs the impact on speed |
| * seems to be minimal. We're using a default buffer size of 4 KB.</p> |
| * |
| * <p>The <code>copy</code> methods use an internal buffer when copying. It is therefore advisable |
| * <em>not</em> to deliberately wrap the stream arguments to the <code>copy</code> methods in |
| * <code>Buffered*</code> streams. For example, don't do the |
| * following:</p> |
| * |
| * <code>copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );</code> |
| * |
| * <p>The rationale is as follows:</p> |
| * |
| * <p>Imagine that an InputStream's read() is a very expensive operation, which would usually suggest |
| * wrapping in a BufferedInputStream. The BufferedInputStream works by issuing infrequent |
| * {@link java.io.InputStream#read(byte[] b, int off, int len)} requests on the underlying InputStream, to |
| * fill an internal buffer, from which further <code>read</code> requests can inexpensively get |
| * their data (until the buffer runs out).</p> |
| * <p>However, the <code>copy</code> methods do the same thing, keeping an internal buffer, |
| * populated by {@link InputStream#read(byte[] b, int off, int len)} requests. Having two buffers |
| * (or three if the destination stream is also buffered) is pointless, and the unnecessary buffer |
| * management hurts performance slightly (about 3%, according to some simple experiments).</p> |
| * |
| * <p>Behold, intrepid explorers; a map of this class:</p> |
| * <pre> |
| * Method Input Output Dependency |
| * ------ ----- ------ ------- |
| * 1 copy InputStream OutputStream (primitive) |
| * 2 copy Reader Writer (primitive) |
| * |
| * 3 copy InputStream Writer 2 |
| * |
| * 4 copy Reader OutputStream 2 |
| * |
| * 5 copy String OutputStream 2 |
| * 6 copy String Writer (trivial) |
| * |
| * 7 copy byte[] Writer 3 |
| * 8 copy byte[] OutputStream (trivial) |
| * </pre> |
| * |
| * <p>Note that only the first two methods shuffle bytes; the rest use these |
| * two, or (if possible) copy using native Java copy methods. As there are |
| * method variants to specify the encoding, each row may |
| * correspond to up to 2 methods.</p> |
| * |
| * <p>Origin of code: Apache Avalon (Excalibur)</p> |
| * |
| * @author Peter Donald |
| * @author Jeff Turner |
| * @author Matthew Hawthorne |
| * @author Stephen Colebourne |
| * @version $Id: CopyUtils.java,v 1.7 2004/07/31 09:52:09 scolebourne Exp $ |
| */ |
| public class CopyUtils { |
| |
| /** |
| * The default buffer size to use. |
| */ |
| private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; |
| |
| /** |
| * Instances should NOT be constructed in standard programming. |
| */ |
| public CopyUtils() {} |
| |
| // from byte[] |
| //----------------------------------------------------------------------- |
| /** |
| * Copy bytes from a <code>byte[]</code> to an <code>OutputStream</code>. |
| * |
| * @param input the byte array to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(byte[] input, OutputStream output) throws IOException { |
| output.write(input); |
| } |
| |
| /** |
| * Copy bytes from a <code>byte[]</code> to chars on a <code>Writer</code> |
| * using the default character encoding of the platform. |
| * |
| * @param input the byte array to read from |
| * @param output the <code>Writer</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(byte[] input, Writer output) throws IOException { |
| ByteArrayInputStream in = new ByteArrayInputStream(input); |
| copy(in, output); |
| } |
| |
| /** |
| * Copy bytes from a <code>byte[]</code> to chars on a <code>Writer</code> |
| * using the specified character encoding. |
| * <p> |
| * Character encoding names can be found at |
| * <a href="http://www.iana.org/assignments/character-sets">IANA</a>. |
| * |
| * @param input the byte array to read from |
| * @param output the <code>Writer</code> to write to |
| * @param encoding the encoding to use, null means platform default |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(byte[] input, Writer output, String encoding) throws IOException { |
| ByteArrayInputStream in = new ByteArrayInputStream(input); |
| copy(in, output, encoding); |
| } |
| |
| // from InputStream |
| //----------------------------------------------------------------------- |
| /** |
| * Copy bytes from an <code>InputStream</code> to an <code>OutputStream</code>. |
| * |
| * @param input the <code>InputStream</code> to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @return the number of bytes copied |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static int copy(InputStream input, OutputStream output) throws IOException { |
| byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; |
| int count = 0; |
| int n = 0; |
| while (-1 != (n = input.read(buffer))) { |
| output.write(buffer, 0, n); |
| count += n; |
| } |
| return count; |
| } |
| |
| /** |
| * Copy bytes from an <code>InputStream</code> to chars on a <code>Writer</code> |
| * using the default character encoding of the platform. |
| * |
| * @param input the <code>InputStream</code> to read from |
| * @param output the <code>Writer</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(InputStream input, Writer output) throws IOException { |
| InputStreamReader in = new InputStreamReader(input); |
| copy(in, output); |
| } |
| |
| /** |
| * Copy bytes from an <code>InputStream</code> to chars on a <code>Writer</code> |
| * using the specified character encoding. |
| * <p> |
| * Character encoding names can be found at |
| * <a href="http://www.iana.org/assignments/character-sets">IANA</a>. |
| * |
| * @param input the <code>InputStream</code> to read from |
| * @param output the <code>Writer</code> to write to |
| * @param encoding the encoding to use, null means platform default |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(InputStream input, Writer output, String encoding) throws IOException { |
| if (encoding == null) { |
| copy(input, output); |
| } else { |
| InputStreamReader in = new InputStreamReader(input, encoding); |
| copy(in, output); |
| } |
| } |
| |
| // from Reader |
| //----------------------------------------------------------------------- |
| /** |
| * Copy chars from a <code>Reader</code> to a <code>Writer</code>. |
| * |
| * @param input the <code>Reader</code> to read from |
| * @param output the <code>Writer</code> to write to |
| * @return the number of characters copied |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static int copy(Reader input, Writer output) throws IOException { |
| char[] buffer = new char[DEFAULT_BUFFER_SIZE]; |
| int count = 0; |
| int n = 0; |
| while (-1 != (n = input.read(buffer))) { |
| output.write(buffer, 0, n); |
| count += n; |
| } |
| return count; |
| } |
| |
| /** |
| * Copy chars from a <code>Reader</code> to bytes on an <code>OutputStream</code> |
| * using the default character encoding of the platform, and calling flush. |
| * <p> |
| * Due to the implementation of OutputStreamWriter, this method performs a flush. |
| * |
| * @param input the <code>Reader</code> to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(Reader input, OutputStream output) throws IOException { |
| OutputStreamWriter out = new OutputStreamWriter(output); |
| copy(input, out); |
| // XXX Unless anyone is planning on rewriting OutputStreamWriter, we have to flush here. |
| out.flush(); |
| } |
| |
| /** |
| * Copy chars from a <code>Reader</code> to bytes on an <code>OutputStream</code> |
| * using the specified character encoding, and calling flush. |
| * <p> |
| * Character encoding names can be found at |
| * <a href="http://www.iana.org/assignments/character-sets">IANA</a>. |
| * <p> |
| * Due to the implementation of OutputStreamWriter, this method performs a flush. |
| * |
| * @param input the <code>Reader</code> to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @param encoding the encoding to use, null means platform default |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(Reader input, OutputStream output, String encoding) throws IOException { |
| if (encoding == null) { |
| copy(input, output); |
| } else { |
| OutputStreamWriter out = new OutputStreamWriter(output, encoding); |
| copy(input, out); |
| // XXX Unless anyone is planning on rewriting OutputStreamWriter, we have to flush here. |
| out.flush(); |
| } |
| } |
| |
| // from String |
| //----------------------------------------------------------------------- |
| /** |
| * Copy chars from a <code>String</code> to a <code>Writer</code>. |
| * |
| * @param input the <code>String</code> to read from |
| * @param output the <code>Writer</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(String input, Writer output) throws IOException { |
| output.write(input); |
| } |
| |
| /** |
| * Copy chars from a <code>String</code> to bytes on an <code>OutputStream</code> |
| * using the default character encoding of the platform, and calling flush. |
| * <p> |
| * Due to the implementation of OutputStreamWriter, this method performs a flush. |
| * |
| * @param input the <code>String</code> to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(String input, OutputStream output) throws IOException { |
| StringReader in = new StringReader(input); |
| OutputStreamWriter out = new OutputStreamWriter(output); |
| copy(in, out); |
| // XXX Unless anyone is planning on rewriting OutputStreamWriter, we have to flush here. |
| out.flush(); |
| } |
| |
| /** |
| * Copy chars from a <code>String</code> to bytes on an <code>OutputStream</code> |
| * using the specified character encoding, and calling flush. |
| * <p> |
| * Character encoding names can be found at |
| * <a href="http://www.iana.org/assignments/character-sets">IANA</a>. |
| * <p> |
| * Due to the implementation of OutputStreamWriter, this method performs a flush. |
| * |
| * @param input the <code>String</code> to read from |
| * @param output the <code>OutputStream</code> to write to |
| * @param encoding the encoding to use, null means platform default |
| * @throws NullPointerException if the input or output is null |
| * @throws IOException if an I/O error occurs |
| */ |
| public static void copy(String input, OutputStream output, String encoding) throws IOException { |
| if (encoding == null) { |
| copy(input, output); |
| } else { |
| StringReader in = new StringReader(input); |
| OutputStreamWriter out = new OutputStreamWriter(output, encoding); |
| copy(in, out); |
| // XXX Unless anyone is planning on rewriting OutputStreamWriter, we have to flush here. |
| out.flush(); |
| } |
| } |
| |
| } |