I've written a class called LimitedInputStream
. It wraps around an existing input stream to limit the number of bytes read from it to a specified length. It's meant as an alternative to:
byte[] data = readAll(length);
InputStream ins = new ByteArrayInputStream(data);
Which requires the extra buffer.
This is the class:
public static class LimitedInputStream extends InputStream {
private final InputStream ins;
private int left;
private int mark = -1;
public LimitedInputStream(InputStream ins, int limit) {
this.ins = ins;
left = limit;
}
public void skipRest() throws IOException {
ByteStreams.skipFully(ins, left);
left = 0;
}
@Override
public int read() throws IOException {
if (left == 0) return -1;
final int read = ins.read();
if (read > 0) left--;
return read;
}
@Override
public int read(byte[] b, int off, int len) throws IOException {
if (left == 0) return -1;
if (len > left) len = left;
final int read = ins.read(b, off, len);
if (read > 0) left -= read;
return read;
}
@Override
public int available() throws IOException {
final int a = ins.available();
return a > left ? left : a;
}
@Override
public void mark(int readlimit) {
ins.mark(readlimit);
mark = left;
}
@Override
public void reset() throws IOException {
if (!ins.markSupported()) throw new IOException("Mark not supported");
if (mark == -1) throw new IOException("Mark not set");
ins.reset();
left = mark;
}
@Override
public long skip(long n) throws IOException {
if (n > left) n = left;
long skipped = ins.skip(n);
left -= skipped;
return skipped;
}
}
Use case:
Object readObj() throws IOException {
int len = readInt();
final LimitedInputStream lis = new LimitedInputStream(this, len);
try {
return deserialize(new CompactInputStream(lis));
} finally {
lis.skipRest();
}
}
for (something) {
Object obj;
try {
obj = readObj();
} catch (Exception e) {
obj = null;
}
list.add(obj);
}
Could you code review my class for any serious bugs, e.g. possible mistakes in updating left
?
Guava includes a LimitInputStream, so you may want to just use that.