    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     */
    017    package org.apache.commons.io.input;
    018
    019    import java.io.IOException;
    020    import java.io.InputStream;
    021
    022    /**
    023     * A decorating input stream that counts the number of bytes that have passed
    024     * through the stream so far.
    025     * <p>
    026     * A typical use case would be during debugging, to ensure that data is being
    027     * read as expected.
    028     *
    029     * @author Marcelo Liberato
    030     * @version $Id: CountingInputStream.java 1004079 2010-10-04 01:11:27Z niallp $
    031     */
    032    public class CountingInputStream extends ProxyInputStream {
    033
    034        /** The count of bytes that have passed. */
    035        private long count;
    036
    037        /**
    038         * Constructs a new CountingInputStream.
    039         *
    040         * @param in  the InputStream to delegate to
    041         */
    042        public CountingInputStream(InputStream in) {
    043            super(in);
    044        }
    045
    046        //-----------------------------------------------------------------------
    047
    048        /**
    049         * Skips the stream over the specified number of bytes, adding the skipped
    050         * amount to the count.
    051         *
    052         * @param length  the number of bytes to skip
    053         * @return the actual number of bytes skipped
    054         * @throws IOException if an I/O error occurs
    055         * @see java.io.InputStream#skip(long)
    056         */
    057        @Override
    058        public synchronized long skip(final long length) throws IOException {
    059            final long skip = super.skip(length);
    060            this.count += skip;
    061            return skip;
    062        }
    063
    064        /**
    065         * Adds the number of read bytes to the count.
    066         *
    067         * @param n number of bytes read, or -1 if no more bytes are available
    068         * @since Commons IO 2.0
    069         */
    070        @Override
    071        protected synchronized void afterRead(int n) {
    072            if (n != -1) {
    073                this.count += n;
    074            }
    075        }
    076
    077        //-----------------------------------------------------------------------
    078        /**
    079         * The number of bytes that have passed through this stream.
    080         * <p>
    081         * NOTE: From v1.3 this method throws an ArithmeticException if the
    082         * count is greater than can be expressed by an <code>int</code>.
    083         * See {@link #getByteCount()} for a method using a <code>long</code>.
    084         *
    085         * @return the number of bytes accumulated
    086         * @throws ArithmeticException if the byte count is too large
    087         */
    088        public int getCount() {
    089            long result = getByteCount();
    090            if (result > Integer.MAX_VALUE) {
    091                throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
    092            }
    093            return (int) result;
    094        }
    095
    096        /**
    097         * Set the byte count back to 0.
    098         * <p>
    099         * NOTE: From v1.3 this method throws an ArithmeticException if the
    100         * count is greater than can be expressed by an <code>int</code>.
    101         * See {@link #resetByteCount()} for a method using a <code>long</code>.
    102         *
    103         * @return the count previous to resetting
    104         * @throws ArithmeticException if the byte count is too large
    105         */
    106        public int resetCount() {
    107            long result = resetByteCount();
    108            if (result > Integer.MAX_VALUE) {
    109                throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
    110            }
    111            return (int) result;
    112        }
    113
    114        /**
    115         * The number of bytes that have passed through this stream.
    116         * <p>
    117         * NOTE: This method is an alternative for <code>getCount()</code>
    118         * and was added because that method returns an integer which will
    119         * result in incorrect count for files over 2GB.
    120         *
    121         * @return the number of bytes accumulated
    122         * @since Commons IO 1.3
    123         */
    124        public synchronized long getByteCount() {
    125            return this.count;
    126        }
    127
    128        /**
    129         * Set the byte count back to 0.
    130         * <p>
    131         * NOTE: This method is an alternative for <code>resetCount()</code>
    132         * and was added because that method returns an integer which will
    133         * result in incorrect count for files over 2GB.
    134         *
    135         * @return the count previous to resetting
    136         * @since Commons IO 1.3
    137         */
    138        public synchronized long resetByteCount() {
    139            long tmp = this.count;
    140            this.count = 0;
    141            return tmp;
    142        }
    143
    144    }