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 }