package be.digitalia.fosdem.utils; import android.support.annotation.NonNull; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; /** * An InputStream which counts the total number of bytes read and notifies a listener. * * @author Christophe Beyls * */ public class ByteCountInputStream extends FilterInputStream { public interface ByteCountListener { void onNewCount(int byteCount); } private final ByteCountListener listener; private final int interval; private int currentBytes = 0; private int nextStepBytes; public ByteCountInputStream(InputStream input, ByteCountListener listener, int interval) { super(input); if (listener == null) { throw new IllegalArgumentException("listener must not be null"); } if (interval <= 0) { throw new IllegalArgumentException("interval must be at least 1 byte"); } this.listener = listener; this.interval = interval; nextStepBytes = interval; listener.onNewCount(0); } @Override public int read() throws IOException { int b = super.read(); addBytes((b == -1) ? -1 : 1); return b; } @Override public int read(@NonNull byte[] buffer, int offset, int max) throws IOException { int count = super.read(buffer, offset, max); addBytes(count); return count; } @Override public boolean markSupported() { return false; } @Override public synchronized void mark(int readlimit) { throw new IllegalStateException(); } @Override public synchronized void reset() throws IOException { throw new IllegalStateException(); } @Override public long skip(long byteCount) throws IOException { long count = super.skip(byteCount); addBytes((int) count); return count; } private void addBytes(int count) { if (count != -1) { currentBytes += count; if (currentBytes < nextStepBytes) { return; } nextStepBytes = currentBytes + interval; } listener.onNewCount(currentBytes); } }