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.output; 18 19 import java.io.OutputStream; 20 21 /** 22 * A decorating output stream that counts the number of bytes that have passed 23 * through the stream so far. 24 * <p> 25 * A typical use case would be during debugging, to ensure that data is being 26 * written as expected. 27 * </p> 28 */ 29 public class CountingOutputStream extends ProxyOutputStream { 30 31 /** The count of bytes that have passed. */ 32 private long count; 33 34 /** 35 * Constructs a new CountingOutputStream. 36 * 37 * @param out the OutputStream to write to 38 */ 39 public CountingOutputStream(final OutputStream out) { 40 super(out); 41 } 42 43 /** 44 * Updates the count with the number of bytes that are being written. 45 * 46 * @param n number of bytes to be written to the stream 47 * @since 2.0 48 */ 49 @Override 50 protected synchronized void beforeWrite(final int n) { 51 count += n; 52 } 53 54 /** 55 * The number of bytes that have passed through this stream. 56 * <p> 57 * NOTE: This method is an alternative for {@code getCount()}. 58 * It was added because that method returns an integer which will 59 * result in incorrect count for files over 2GB. 60 * </p> 61 * 62 * @return the number of bytes accumulated 63 * @since 1.3 64 */ 65 public synchronized long getByteCount() { 66 return this.count; 67 } 68 69 /** 70 * Gets the number of bytes that have passed through this stream. 71 * <p> 72 * NOTE: From v1.3 this method throws an ArithmeticException if the 73 * count is greater than can be expressed by an {@code int}. 74 * See {@link #getByteCount()} for a method using a {@code long}. 75 * </p> 76 * 77 * @return the number of bytes accumulated 78 * @throws ArithmeticException if the byte count is too large 79 */ 80 public int getCount() { 81 final long result = getByteCount(); 82 if (result > Integer.MAX_VALUE) { 83 throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); 84 } 85 return (int) result; 86 } 87 88 /** 89 * Sets the byte count back to 0. 90 * <p> 91 * NOTE: This method is an alternative for {@code resetCount()}. 92 * It was added because that method returns an integer which will 93 * result in incorrect count for files over 2GB. 94 * </p> 95 * 96 * @return the count previous to resetting 97 * @since 1.3 98 */ 99 public synchronized long resetByteCount() { 100 final long tmp = this.count; 101 this.count = 0; 102 return tmp; 103 } 104 105 /** 106 * Sets the byte count back to 0. 107 * <p> 108 * NOTE: From v1.3 this method throws an ArithmeticException if the 109 * count is greater than can be expressed by an {@code int}. 110 * See {@link #resetByteCount()} for a method using a {@code long}. 111 * </p> 112 * 113 * @return the count previous to resetting 114 * @throws ArithmeticException if the byte count is too large 115 */ 116 public int resetCount() { 117 final long result = resetByteCount(); 118 if (result > Integer.MAX_VALUE) { 119 throw new ArithmeticException("The byte count " + result + " is too large to be converted to an int"); 120 } 121 return (int) result; 122 } 123 124 }