1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/* 2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more 3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements. See the NOTICE file distributed with 4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership. 5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0 6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with 7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License. You may obtain a copy of the License at 8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * http://www.apache.org/licenses/LICENSE-2.0 10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software 12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS, 13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and 15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License. 16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.input; 18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException; 20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.InputStream; 21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/** 23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * A decorating input stream that counts the number of bytes that have passed 24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * through the stream so far. 25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p> 26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * A typical use case would be during debugging, to ensure that data is being 27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * read as expected. 28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @author Marcelo Liberato 30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: CountingInputStream.java 471628 2006-11-06 04:06:45Z bayard $ 31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class CountingInputStream extends ProxyInputStream { 33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** The count of bytes that have passed. */ 35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook private long count; 36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Constructs a new CountingInputStream. 39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param in the InputStream to delegate to 41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public CountingInputStream(InputStream in) { 43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook super(in); 44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook //----------------------------------------------------------------------- 47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Reads a number of bytes into the byte array, keeping count of the 49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * number read. 50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param b the buffer into which the data is read, not null 52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the total number of bytes read into the buffer, -1 if end of stream 53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws IOException if an I/O error occurs 54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @see java.io.InputStream#read(byte[]) 55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public int read(byte[] b) throws IOException { 57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int found = super.read(b); 58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.count += (found >= 0) ? found : 0; 59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return found; 60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Reads a number of bytes into the byte array at a specific offset, 64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * keeping count of the number read. 65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param b the buffer into which the data is read, not null 67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param off the start offset in the buffer 68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param len the maximum number of bytes to read 69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the total number of bytes read into the buffer, -1 if end of stream 70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws IOException if an I/O error occurs 71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @see java.io.InputStream#read(byte[], int, int) 72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public int read(byte[] b, int off, int len) throws IOException { 74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int found = super.read(b, off, len); 75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.count += (found >= 0) ? found : 0; 76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return found; 77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Reads the next byte of data adding to the count of bytes received 81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * if a byte is successfully read. 82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the byte read, -1 if end of stream 84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws IOException if an I/O error occurs 85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @see java.io.InputStream#read() 86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public int read() throws IOException { 88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook int found = super.read(); 89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.count += (found >= 0) ? 1 : 0; 90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return found; 91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Skips the stream over the specified number of bytes, adding the skipped 95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * amount to the count. 96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @param length the number of bytes to skip 98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the actual number of bytes skipped 99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws IOException if an I/O error occurs 100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @see java.io.InputStream#skip(long) 101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public long skip(final long length) throws IOException { 103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook final long skip = super.skip(length); 104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.count += skip; 105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return skip; 106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook //----------------------------------------------------------------------- 109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The number of bytes that have passed through this stream. 111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p> 112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * NOTE: From v1.3 this method throws an ArithmeticException if the 113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * count is greater than can be expressed by an <code>int</code>. 114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See {@link #getByteCount()} for a method using a <code>long</code>. 115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the number of bytes accumulated 117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws ArithmeticException if the byte count is too large 118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public synchronized int getCount() { 120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook long result = getByteCount(); 121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (result > Integer.MAX_VALUE) { 122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); 123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return (int) result; 125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Set the byte count back to 0. 129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p> 130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * NOTE: From v1.3 this method throws an ArithmeticException if the 131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * count is greater than can be expressed by an <code>int</code>. 132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See {@link #resetByteCount()} for a method using a <code>long</code>. 133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the count previous to resetting 135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @throws ArithmeticException if the byte count is too large 136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public synchronized int resetCount() { 138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook long result = resetByteCount(); 139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook if (result > Integer.MAX_VALUE) { 140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); 141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return (int) result; 143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The number of bytes that have passed through this stream. 147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p> 148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * NOTE: This method is an alternative for <code>getCount()</code> 149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * and was added because that method returns an integer which will 150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * result in incorrect count for files over 2GB. 151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the number of bytes accumulated 153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.3 154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public synchronized long getByteCount() { 156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return this.count; 157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook /** 160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Set the byte count back to 0. 161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p> 162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * NOTE: This method is an alternative for <code>resetCount()</code> 163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * and was added because that method returns an integer which will 164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * result in incorrect count for files over 2GB. 165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * 166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @return the count previous to resetting 167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @since Commons IO 1.3 168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */ 169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook public synchronized long resetByteCount() { 170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook long tmp = this.count; 171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook this.count = 0; 172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook return tmp; 173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook } 174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook 175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook} 176