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 * https://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 static org.apache.commons.io.IOUtils.EOF;
20
21 import java.io.IOException;
22 import java.io.InputStream;
23
24 /**
25 * A decorating input stream that counts the number of bytes that have passed
26 * through the stream so far.
27 * <p>
28 * A typical use case would be during debugging, to ensure that data is being
29 * read as expected.
30 * </p>
31 *
32 * @deprecated Use {@link BoundedInputStream} (unbounded by default).
33 */
34 @Deprecated
35 public class CountingInputStream extends ProxyInputStream {
36
37 /** The count of bytes read. */
38 private long count;
39
40 /**
41 * Constructs a new CountingInputStream.
42 *
43 * @param in the InputStream to delegate to
44 */
45 public CountingInputStream(final InputStream in) {
46 super(in);
47 }
48
49 CountingInputStream(final InputStream in, final ProxyInputStream.AbstractBuilder<?, ?> builder) {
50 super(in, builder);
51 }
52
53 CountingInputStream(final ProxyInputStream.AbstractBuilder<?, ?> builder) throws IOException {
54 super(builder);
55 }
56
57 /**
58 * Adds the number of read bytes to the count.
59 *
60 * @param n number of bytes read, or -1 if no more bytes are available
61 * @throws IOException Not thrown here but subclasses may throw.
62 * @since 2.0
63 */
64 @Override
65 protected synchronized void afterRead(final int n) throws IOException {
66 if (n != EOF) {
67 count += n;
68 }
69 super.afterRead(n);
70 }
71
72 /**
73 * Gets number of bytes that have passed through this stream.
74 * <p>
75 * NOTE: This method is an alternative for {@code getCount()}
76 * and was added because that method returns an integer which will
77 * result in incorrect count for files over 2GB.
78 * </p>
79 *
80 * @return the number of bytes accumulated
81 * @since 1.3
82 */
83 public synchronized long getByteCount() {
84 return count;
85 }
86
87 /**
88 * Gets number of bytes that have passed through this stream.
89 * <p>
90 * This method throws an ArithmeticException if the
91 * count is greater than can be expressed by an {@code int}.
92 * See {@link #getByteCount()} for a method using a {@code long}.
93 * </p>
94 *
95 * @return the number of bytes accumulated
96 * @throws ArithmeticException if the byte count is too large
97 * @deprecated Use {@link #getByteCount()}.
98 */
99 @Deprecated
100 public int getCount() {
101 final long result = getByteCount();
102 if (result > Integer.MAX_VALUE) {
103 throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
104 }
105 return (int) result;
106 }
107
108 /**
109 * Resets the byte count back to 0.
110 * <p>
111 * NOTE: This method is an alternative for {@code resetCount()}
112 * and was added because that method returns an integer which will
113 * result in incorrect count for files over 2GB.
114 * </p>
115 *
116 * @return the count previous to resetting
117 * @since 1.3
118 */
119 public synchronized long resetByteCount() {
120 final long tmp = count;
121 count = 0;
122 return tmp;
123 }
124
125 /**
126 * Resets the byte count back to 0.
127 * <p>
128 * This method throws an ArithmeticException if the
129 * count is greater than can be expressed by an {@code int}.
130 * See {@link #resetByteCount()} for a method using a {@code long}.
131 * </p>
132 *
133 * @return the count previous to resetting
134 * @throws ArithmeticException if the byte count is too large
135 * @deprecated Use {@link #resetByteCount()}.
136 */
137 @Deprecated
138 public int resetCount() {
139 final long result = resetByteCount();
140 if (result > Integer.MAX_VALUE) {
141 throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int");
142 }
143 return (int) result;
144 }
145
146 /**
147 * Skips the stream over the specified number of bytes, adding the skipped
148 * amount to the count.
149 *
150 * @param length the number of bytes to skip
151 * @return the actual number of bytes skipped
152 * @throws IOException if an I/O error occurs.
153 * @see InputStream#skip(long)
154 */
155 @Override
156 public synchronized long skip(final long length) throws IOException {
157 final long skip = super.skip(length);
158 count += skip;
159 return skip;
160 }
161
162 }