views:

92

answers:

4

I want to create an InputStream that is limited to a certain range of bytes in file, e.g. to bytes from position 0 to 100. So that the client code should see EOF once 100th byte is reached.

+5  A: 

The read() method of InputStream reads a single byte at a time. You could write a subclass of InputStream that maintains an internal counter; each time read() is called, update the counter. If you have hit your maximum, do not allow any further reads (return -1 or something like that).

You will also need to ensure that the other methods for reading read_int, etc are unsupported.

I don't know what your use case is, but as a bonus you may want to implement buffering as well.

danben
I don't think there is any need to implement buffering - that's mixing concerns, and the way read(byte[]) works, returning up to the required amount of data, makes this unnecessary. It's cleaner and equally effective to wrap the base stream in a BufferedInputStream.
mdma
+2  A: 

If you only need 100 bytes, then simple is probably best, I'd read them into an array and wrap that as a ByteArrayInputStream. E.g.

   int length = 100;
   byte[] data = new byte[length];
   InputStream in = ...;  //your inputstream
   DataInputStream din = new DataInputStream(din);
   din.readFully(data);
   ByteArrayInputStream first100Bytes = new ByteArrayInputStream(data);
   // pass first100bytes to your clients

If you don't want to use DataInputStream.readFully, there is IOUtils.readFully from apache commons-io, or you can implment the read loop explicitly.

If you have more advanced needs, such as reading from a segment in the middle of the file, or larger amounts of data, then extending InputStream and overriding the read(byte[], int,int) as well as read(), will give you better performance than just overriding the read() method.

mdma
+4  A: 

As danben says, just decorate your stream and enforce the constraint:

public class ConstrainedInputStream extends InputStream {
  private final InputStream decorated;
  private long length;

  public ConstrainedInputStream(InputStream decorated, long length) {
    this.decorated = decorated;
    this.length = length;
  }

  @Override public int read() throws IOException {
    return (length-- <= 0) ? -1 : decorated.read();
  }

  // TODO: override other methods if you feel it's necessary
  // optionally, extend FilterInputStream instead
}
McDowell