My personal choice is an InputStream wrapper that counts bytes as it reads them:
public class LimitedSizeInputStream extends InputStream {
private final InputStream original;
private final long maxSize;
private long total;
public LimitedSizeInputStream(InputStream original, long maxSize) {
this.original = original;
this.maxSize = maxSize;
}
@Override
public int read() throws IOException {
int i = original.read();
if (i>=0) incrementCounter(1);
return i;
}
@Override
public int read(byte b[]) throws IOException {
return read(b, 0, b.length);
}
@Override
public int read(byte b[], int off, int len) throws IOException {
int i = original.read(b, off, len);
if (i>=0) incrementCounter(i);
return i;
}
private void incrementCounter(int size) throws IOException {
total += size;
if (total>maxSize) throw new IOException("InputStream exceeded maximum size in bytes.");
}
}
I like this approach because it is transparent, it is re-usable with all input streams and it works well with other libraries. For example copying files up to 4KB with Apache Commons:
InputStream in = new LimitedSizeInputStream(new FileInputStream("from.txt"), 4096);
OutputStream out = new FileOutputStream("to.txt");
IOUtils.copy(in, out);
PS: The main difference of the implementation above with BoundedInputStream is that BoundedInputStream does not throw an exception when the limit is exceeded (it just closes the stream)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…