View Javadoc

    1   /*
    2    * Copyright 2001-2005 The Apache Software Foundation
    3    *
    4    * Licensed under the Apache License, Version 2.0 (the "License");
    5    * you may not use this file except in compliance with the License.
    6    * You may obtain a copy of the License at
    7    *
    8    *     http://www.apache.org/licenses/LICENSE-2.0
    9    *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  package org.apache.commons.net.io;
    17
    18  import java.io.IOException;
    19  import java.io.InputStream;
    20  import java.io.OutputStream;
    21  import java.io.Reader;
    22  import java.io.Writer;
    23
    24  /****
    25   * The Util class cannot be instantiated and stores short static convenience
    26   * methods that are often quite useful.
    27   * <p>
    28   * <p>
    29   * @see CopyStreamException
    30   * @see CopyStreamListener
    31   * @see CopyStreamAdapter
    32   * @author Daniel F. Savarese
    33   ***/
    34
    35  public final class Util
    36  {
    37      /****
    38       * The default buffer size used by {@link #copyStream  copyStream }
    39       * and {@link #copyReader  copyReader }. It's value is 1024.
    40       ***/
    41      public static final int DEFAULT_COPY_BUFFER_SIZE = 1024;
    42
    43      // Cannot be instantiated
    44      private Util()
    45      { }
    46
    47
    48      /****
    49       * Copies the contents of an InputStream to an OutputStream using a
    50       * copy buffer of a given size and notifies the provided
    51       * CopyStreamListener of the progress of the copy operation by calling
    52       * its bytesTransferred(long, int) method after each write to the
    53       * destination.  If you wish to notify more than one listener you should
    54       * use a CopyStreamAdapter as the listener and register the additional
    55       * listeners with the CopyStreamAdapter.
    56       * <p>
    57       * The contents of the InputStream are
    58       * read until the end of the stream is reached, but neither the
    59       * source nor the destination are closed.  You must do this yourself
    60       * outside of the method call.  The number of bytes read/written is
    61       * returned.
    62       * <p>
    63       * @param source  The source InputStream.
    64       * @param dest    The destination OutputStream.
    65       * @param bufferSize  The number of bytes to buffer during the copy.
    66       * @param streamSize  The number of bytes in the stream being copied.
    67       *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
    68       * @param listener  The CopyStreamListener to notify of progress.  If
    69       *      this parameter is null, notification is not attempted.
    70       * @param flush Whether to flush the output stream after every
    71       *        write.  This is necessary for interactive sessions that rely on
    72       *        buffered streams.  If you don't flush, the data will stay in
    73       *        the stream buffer.
    74       * @exception CopyStreamException  If an error occurs while reading from the
    75       *            source or writing to the destination.  The CopyStreamException
    76       *            will contain the number of bytes confirmed to have been
    77       *            transferred before an
    78       *            IOException occurred, and it will also contain the IOException
    79       *            that caused the error.  These values can be retrieved with
    80       *            the CopyStreamException getTotalBytesTransferred() and
    81       *            getIOException() methods.
    82       ***/
    83      public static final long copyStream(InputStream source, OutputStream dest,
    84                                          int bufferSize, long streamSize,
    85                                          CopyStreamListener listener,
    86                                          boolean flush)
    87      throws CopyStreamException
    88      {
    89          int bytes;
    90          long total;
    91          byte[] buffer;
    92
    93          buffer = new byte[bufferSize];
    94          total = 0;
    95
    96          try
    97          {
    98              while ((bytes = source.read(buffer)) != -1)
    99              {
    100                 // Technically, some read(byte[]) methods may return 0 and we cannot
    101                 // accept that as an indication of EOF.
    102
    103                 if (bytes == 0)
    104                 {
    105                     bytes = source.read();
    106                     if (bytes < 0)
    107                         break;
    108                     dest.write(bytes);
    109                     if(flush)
    110                       dest.flush();
    111                     ++total;
    112                     if (listener != null)
    113                         listener.bytesTransferred(total, 1, streamSize);
    114                     continue;
    115                 }
    116
    117                 dest.write(buffer, 0, bytes);
    118                 if(flush)
    119                   dest.flush();
    120                 total += bytes;
    121                 if (listener != null)
    122                     listener.bytesTransferred(total, bytes, streamSize);
    123             }
    124         }
    125         catch (IOException e)
    126         {
    127             throw new CopyStreamException("IOException caught while copying.",
    128                                           total, e);
    129         }
    130
    131         return total;
    132     }
    133
    134
    135     /****
    136      * Copies the contents of an InputStream to an OutputStream using a
    137      * copy buffer of a given size and notifies the provided
    138      * CopyStreamListener of the progress of the copy operation by calling
    139      * its bytesTransferred(long, int) method after each write to the
    140      * destination.  If you wish to notify more than one listener you should
    141      * use a CopyStreamAdapter as the listener and register the additional
    142      * listeners with the CopyStreamAdapter.
    143      * <p>
    144      * The contents of the InputStream are
    145      * read until the end of the stream is reached, but neither the
    146      * source nor the destination are closed.  You must do this yourself
    147      * outside of the method call.  The number of bytes read/written is
    148      * returned.
    149      * <p>
    150      * @param source  The source InputStream.
    151      * @param dest    The destination OutputStream.
    152      * @param bufferSize  The number of bytes to buffer during the copy.
    153      * @param streamSize  The number of bytes in the stream being copied.
    154      *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
    155      * @param listener  The CopyStreamListener to notify of progress.  If
    156      *      this parameter is null, notification is not attempted.
    157      * @exception CopyStreamException  If an error occurs while reading from the
    158      *            source or writing to the destination.  The CopyStreamException
    159      *            will contain the number of bytes confirmed to have been
    160      *            transferred before an
    161      *            IOException occurred, and it will also contain the IOException
    162      *            that caused the error.  These values can be retrieved with
    163      *            the CopyStreamException getTotalBytesTransferred() and
    164      *            getIOException() methods.
    165      ***/
    166     public static final long copyStream(InputStream source, OutputStream dest,
    167                                         int bufferSize, long streamSize,
    168                                         CopyStreamListener listener)
    169     throws CopyStreamException
    170     {
    171       return copyStream(source, dest, bufferSize, streamSize, listener,
    172                         true);
    173     }
    174
    175
    176     /****
    177      * Copies the contents of an InputStream to an OutputStream using a
    178      * copy buffer of a given size.  The contents of the InputStream are
    179      * read until the end of the stream is reached, but neither the
    180      * source nor the destination are closed.  You must do this yourself
    181      * outside of the method call.  The number of bytes read/written is
    182      * returned.
    183      * <p>
    184      * @param source  The source InputStream.
    185      * @param dest    The destination OutputStream.
    186      * @return  The number of bytes read/written in the copy operation.
    187      * @exception CopyStreamException  If an error occurs while reading from the
    188      *            source or writing to the destination.  The CopyStreamException
    189      *            will contain the number of bytes confirmed to have been
    190      *            transferred before an
    191      *            IOException occurred, and it will also contain the IOException
    192      *            that caused the error.  These values can be retrieved with
    193      *            the CopyStreamException getTotalBytesTransferred() and
    194      *            getIOException() methods.
    195      ***/
    196     public static final long copyStream(InputStream source, OutputStream dest,
    197                                         int bufferSize)
    198     throws CopyStreamException
    199     {
    200         return copyStream(source, dest, bufferSize,
    201                           CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
    202     }
    203
    204
    205     /****
    206      * Same as <code> copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
    207      ***/
    208     public static final long copyStream(InputStream source, OutputStream dest)
    209     throws CopyStreamException
    210     {
    211         return copyStream(source, dest, DEFAULT_COPY_BUFFER_SIZE);
    212     }
    213
    214
    215     /****
    216      * Copies the contents of a Reader to a Writer using a
    217      * copy buffer of a given size and notifies the provided
    218      * CopyStreamListener of the progress of the copy operation by calling
    219      * its bytesTransferred(long, int) method after each write to the
    220      * destination.  If you wish to notify more than one listener you should
    221      * use a CopyStreamAdapter as the listener and register the additional
    222      * listeners with the CopyStreamAdapter.
    223      * <p>
    224      * The contents of the Reader are
    225      * read until its end is reached, but neither the source nor the
    226      * destination are closed.  You must do this yourself outside of the
    227      * method call.  The number of characters read/written is returned.
    228      * <p>
    229      * @param source  The source Reader.
    230      * @param dest    The destination writer.
    231      * @param bufferSize  The number of characters to buffer during the copy.
    232      * @param streamSize  The number of characters in the stream being copied.
    233      *          Should be set to CopyStreamEvent.UNKNOWN_STREAM_SIZE if unknown.
    234      * @param listener  The CopyStreamListener to notify of progress.  If
    235      *      this parameter is null, notification is not attempted.
    236      * @return  The number of characters read/written in the copy operation.
    237      * @exception CopyStreamException  If an error occurs while reading from the
    238      *            source or writing to the destination.  The CopyStreamException
    239      *            will contain the number of bytes confirmed to have been
    240      *            transferred before an
    241      *            IOException occurred, and it will also contain the IOException
    242      *            that caused the error.  These values can be retrieved with
    243      *            the CopyStreamException getTotalBytesTransferred() and
    244      *            getIOException() methods.
    245      ***/
    246     public static final long copyReader(Reader source, Writer dest,
    247                                         int bufferSize, long streamSize,
    248                                         CopyStreamListener listener)
    249     throws CopyStreamException
    250     {
    251         int chars;
    252         long total;
    253         char[] buffer;
    254
    255         buffer = new char[bufferSize];
    256         total = 0;
    257
    258         try
    259         {
    260             while ((chars = source.read(buffer)) != -1)
    261             {
    262                 // Technically, some read(char[]) methods may return 0 and we cannot
    263                 // accept that as an indication of EOF.
    264                 if (chars == 0)
    265                 {
    266                     chars = source.read();
    267                     if (chars < 0)
    268                         break;
    269                     dest.write(chars);
    270                     dest.flush();
    271                     ++total;
    272                     if (listener != null)
    273                         listener.bytesTransferred(total, chars, streamSize);
    274                     continue;
    275                 }
    276
    277                 dest.write(buffer, 0, chars);
    278                 dest.flush();
    279                 total += chars;
    280                 if (listener != null)
    281                     listener.bytesTransferred(total, chars, streamSize);
    282             }
    283         }
    284         catch (IOException e)
    285         {
    286             throw new CopyStreamException("IOException caught while copying.",
    287                                           total, e);
    288         }
    289
    290         return total;
    291     }
    292
    293
    294     /****
    295      * Copies the contents of a Reader to a Writer using a
    296      * copy buffer of a given size.  The contents of the Reader are
    297      * read until its end is reached, but neither the source nor the
    298      * destination are closed.  You must do this yourself outside of the
    299      * method call.  The number of characters read/written is returned.
    300      * <p>
    301      * @param source  The source Reader.
    302      * @param dest    The destination writer.
    303      * @param bufferSize  The number of characters to buffer during the copy.
    304      * @return  The number of characters read/written in the copy operation.
    305      * @exception CopyStreamException  If an error occurs while reading from the
    306      *            source or writing to the destination.  The CopyStreamException
    307      *            will contain the number of bytes confirmed to have been
    308      *            transferred before an
    309      *            IOException occurred, and it will also contain the IOException
    310      *            that caused the error.  These values can be retrieved with
    311      *            the CopyStreamException getTotalBytesTransferred() and
    312      *            getIOException() methods.
    313      ***/
    314     public static final long copyReader(Reader source, Writer dest,
    315                                         int bufferSize)
    316     throws CopyStreamException
    317     {
    318         return copyReader(source, dest, bufferSize,
    319                           CopyStreamEvent.UNKNOWN_STREAM_SIZE, null);
    320     }
    321
    322
    323     /****
    324      * Same as <code> copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE); </code>
    325      ***/
    326     public static final long copyReader(Reader source, Writer dest)
    327     throws CopyStreamException
    328     {
    329         return copyReader(source, dest, DEFAULT_COPY_BUFFER_SIZE);
    330     }
    331
    332 }