Home | History | Annotate | Download | only in input
      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.input;
     18 
     19 import java.io.IOException;
     20 import java.io.InputStream;
     21 
     22 /**
     23  * A decorating input stream that counts the number of bytes that have passed
     24  * through the stream so far.
     25  * <p>
     26  * A typical use case would be during debugging, to ensure that data is being
     27  * read as expected.
     28  *
     29  * @author Marcelo Liberato
     30  * @version $Id: CountingInputStream.java 471628 2006-11-06 04:06:45Z bayard $
     31  */
     32 public class CountingInputStream extends ProxyInputStream {
     33 
     34     /** The count of bytes that have passed. */
     35     private long count;
     36 
     37     /**
     38      * Constructs a new CountingInputStream.
     39      *
     40      * @param in  the InputStream to delegate to
     41      */
     42     public CountingInputStream(InputStream in) {
     43         super(in);
     44     }
     45 
     46     //-----------------------------------------------------------------------
     47     /**
     48      * Reads a number of bytes into the byte array, keeping count of the
     49      * number read.
     50      *
     51      * @param b  the buffer into which the data is read, not null
     52      * @return the total number of bytes read into the buffer, -1 if end of stream
     53      * @throws IOException if an I/O error occurs
     54      * @see java.io.InputStream#read(byte[])
     55      */
     56     public int read(byte[] b) throws IOException {
     57         int found = super.read(b);
     58         this.count += (found >= 0) ? found : 0;
     59         return found;
     60     }
     61 
     62     /**
     63      * Reads a number of bytes into the byte array at a specific offset,
     64      * keeping count of the number read.
     65      *
     66      * @param b  the buffer into which the data is read, not null
     67      * @param off  the start offset in the buffer
     68      * @param len  the maximum number of bytes to read
     69      * @return the total number of bytes read into the buffer, -1 if end of stream
     70      * @throws IOException if an I/O error occurs
     71      * @see java.io.InputStream#read(byte[], int, int)
     72      */
     73     public int read(byte[] b, int off, int len) throws IOException {
     74         int found = super.read(b, off, len);
     75         this.count += (found >= 0) ? found : 0;
     76         return found;
     77     }
     78 
     79     /**
     80      * Reads the next byte of data adding to the count of bytes received
     81      * if a byte is successfully read.
     82      *
     83      * @return the byte read, -1 if end of stream
     84      * @throws IOException if an I/O error occurs
     85      * @see java.io.InputStream#read()
     86      */
     87     public int read() throws IOException {
     88         int found = super.read();
     89         this.count += (found >= 0) ? 1 : 0;
     90         return found;
     91     }
     92 
     93     /**
     94      * Skips the stream over the specified number of bytes, adding the skipped
     95      * amount to the count.
     96      *
     97      * @param length  the number of bytes to skip
     98      * @return the actual number of bytes skipped
     99      * @throws IOException if an I/O error occurs
    100      * @see java.io.InputStream#skip(long)
    101      */
    102     public long skip(final long length) throws IOException {
    103         final long skip = super.skip(length);
    104         this.count += skip;
    105         return skip;
    106     }
    107 
    108     //-----------------------------------------------------------------------
    109     /**
    110      * The number of bytes that have passed through this stream.
    111      * <p>
    112      * NOTE: From v1.3 this method throws an ArithmeticException if the
    113      * count is greater than can be expressed by an <code>int</code>.
    114      * See {@link #getByteCount()} for a method using a <code>long</code>.
    115      *
    116      * @return the number of bytes accumulated
    117      * @throws ArithmeticException if the byte count is too large
    118      */
    119     public synchronized int getCount() {
    120         long result = getByteCount();
    121         if (result > Integer.MAX_VALUE) {
    122             throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
    123         }
    124         return (int) result;
    125     }
    126 
    127     /**
    128      * Set the byte count back to 0.
    129      * <p>
    130      * NOTE: From v1.3 this method throws an ArithmeticException if the
    131      * count is greater than can be expressed by an <code>int</code>.
    132      * See {@link #resetByteCount()} for a method using a <code>long</code>.
    133      *
    134      * @return the count previous to resetting
    135      * @throws ArithmeticException if the byte count is too large
    136      */
    137     public synchronized int resetCount() {
    138         long result = resetByteCount();
    139         if (result > Integer.MAX_VALUE) {
    140             throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
    141         }
    142         return (int) result;
    143     }
    144 
    145     /**
    146      * The number of bytes that have passed through this stream.
    147      * <p>
    148      * NOTE: This method is an alternative for <code>getCount()</code>
    149      * and was added because that method returns an integer which will
    150      * result in incorrect count for files over 2GB.
    151      *
    152      * @return the number of bytes accumulated
    153      * @since Commons IO 1.3
    154      */
    155     public synchronized long getByteCount() {
    156         return this.count;
    157     }
    158 
    159     /**
    160      * Set the byte count back to 0.
    161      * <p>
    162      * NOTE: This method is an alternative for <code>resetCount()</code>
    163      * and was added because that method returns an integer which will
    164      * result in incorrect count for files over 2GB.
    165      *
    166      * @return the count previous to resetting
    167      * @since Commons IO 1.3
    168      */
    169     public synchronized long resetByteCount() {
    170         long tmp = this.count;
    171         this.count = 0;
    172         return tmp;
    173     }
    174 
    175 }
    176