Mega Code Archive

 
Categories / Java Tutorial / File
 

Buffered copying

/*  * Licensed to the Apache Software Foundation (ASF) under one or more  * contributor license agreements.  See the NOTICE file distributed with  * this work for additional information regarding copyright ownership.  * The ASF licenses this file to You 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.  */ 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; /**  * 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>).  *   * 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>.  *   * 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  * 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.  *   * 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:  * <pre>  *  copy( new BufferedInputStream( in ), new BufferedOutputStream( out ) );  *  </pre>  * The rationale is as follows:  *   * 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).  *   * 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).  *   * Behold, intrepid explorers; a map of this class:  * <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>  *   * 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.  *   * Origin of code: Excalibur.  *  * @author Peter Donald  * @author Jeff Turner  * @author Matthew Hawthorne  * @version $Id: CopyUtils.java 437680 2006-08-28 11:57:00Z scolebourne $  */ public class CopyUtils {     /**      * The default size of the buffer.      */     private static final int DEFAULT_BUFFER_SIZE = 1024 * 4;     /**      * Instances should NOT be constructed in standard programming.      */     public CopyUtils() { }     // ----------------------------------------------------------------     // byte[] -> OutputStream     // ----------------------------------------------------------------     /**      * 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 IOException In case of an I/O problem      */     public static void copy(byte[] input, OutputStream output)             throws IOException {         output.write(input);     }     // ----------------------------------------------------------------     // byte[] -> Writer     // ----------------------------------------------------------------     /**      * Copy and convert bytes from a <code>byte[]</code> to chars on a      * <code>Writer</code>.      * The platform's default encoding is used for the byte-to-char conversion.      * @param input the byte array to read from      * @param output the <code>Writer</code> to write to      * @throws IOException In case of an I/O problem      */     public static void copy(byte[] input, Writer output)             throws IOException {         ByteArrayInputStream in = new ByteArrayInputStream(input);         copy(in, output);     }     /**      * Copy and convert bytes from a <code>byte[]</code> to chars on a      * <code>Writer</code>, using the specified encoding.      * @param input the byte array to read from      * @param output the <code>Writer</code> to write to      * @param encoding The name of a supported character encoding. See the      * <a href="http://www.iana.org/assignments/character-sets">IANA      * Charset Registry</a> for a list of valid encoding types.      * @throws IOException In case of an I/O problem      */     public static void copy(             byte[] input,             Writer output,             String encoding)                 throws IOException {         ByteArrayInputStream in = new ByteArrayInputStream(input);         copy(in, output, encoding);     }     // ----------------------------------------------------------------     // Core copy methods     // ----------------------------------------------------------------     /**      * 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 IOException In case of an I/O problem      */     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;     }     // ----------------------------------------------------------------     // Reader -> Writer     // ----------------------------------------------------------------     /**      * 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 IOException In case of an I/O problem      */     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;     }     // ----------------------------------------------------------------     // InputStream -> Writer     // ----------------------------------------------------------------     /**      * Copy and convert bytes from an <code>InputStream</code> to chars on a      * <code>Writer</code>.      * The platform's default encoding is used for the byte-to-char conversion.      * @param input the <code>InputStream</code> to read from      * @param output the <code>Writer</code> to write to      * @throws IOException In case of an I/O problem      */     public static void copy(             InputStream input,             Writer output)                 throws IOException {         InputStreamReader in = new InputStreamReader(input);         copy(in, output);     }     /**      * Copy and convert bytes from an <code>InputStream</code> to chars on a      * <code>Writer</code>, using the specified encoding.      * @param input the <code>InputStream</code> to read from      * @param output the <code>Writer</code> to write to      * @param encoding The name of a supported character encoding. See the      * <a href="http://www.iana.org/assignments/character-sets">IANA      * Charset Registry</a> for a list of valid encoding types.      * @throws IOException In case of an I/O problem      */     public static void copy(             InputStream input,             Writer output,             String encoding)                 throws IOException {         InputStreamReader in = new InputStreamReader(input, encoding);         copy(in, output);     }     // ----------------------------------------------------------------     // Reader -> OutputStream     // ----------------------------------------------------------------     /**      * Serialize chars from a <code>Reader</code> to bytes on an      * <code>OutputStream</code>, and flush the <code>OutputStream</code>.      * @param input the <code>Reader</code> to read from      * @param output the <code>OutputStream</code> to write to      * @throws IOException In case of an I/O problem      */     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();     }     // ----------------------------------------------------------------     // String -> OutputStream     // ----------------------------------------------------------------     /**      * Serialize chars from a <code>String</code> to bytes on an      * <code>OutputStream</code>, and      * flush the <code>OutputStream</code>.      * @param input the <code>String</code> to read from      * @param output the <code>OutputStream</code> to write to      * @throws IOException In case of an I/O problem      */     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();     }     // ----------------------------------------------------------------     // String -> Writer     // ----------------------------------------------------------------     /**      * 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 IOException In case of an I/O problem      */     public static void copy(String input, Writer output)                 throws IOException {         output.write(input);     } }