如何创建约束的InputStream以只读取部分文件?

时间:2010-05-22 13:57:25

标签: java inputstream

我想创建一个仅限于文件中某个字节范围的InputStream,例如从位置0到100的字节。因此客户端代码应在达到第100个字节时看到EOF。

7 个答案:

答案 0 :(得分:10)

read() InputStream方法一次读取一个字节。你可以编写一个InputStream的子类来维护一个内部计数器;每次调用read()时,都要更新计数器。如果达到最大值,则不允许进一步读取(返回-1或类似的东西)。

您还需要确保不支持读取read_int等其他方法(例如:覆盖它们并抛出UnsupportedOperationException());

我不知道你的用例是什么,但作为奖励,你可能也希望实现缓冲。

答案 1 :(得分:8)

作为danben says,只需装饰你的流并强制执行约束:

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
}

答案 2 :(得分:4)

答案 3 :(得分:2)

如果你只需要100个字节,那么simple可能是最好的,我将它们读入一个数组并将其包装为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

如果您不想使用DataInputStream.readFully,那么apache commons-io中会有IOUtils.readFully,或者您可以明确地使用读取循环。

如果您有更高级的需求,例如从文件中间的段读取,或者更大量的数据,那么扩展InputStream并覆盖read(byte [],int,int)以及read( ),将提供比仅覆盖read()方法更好的性能。

答案 4 :(得分:2)

你可以使用番石榴的ByteStreams。 请注意,您应该在limit之前使用skipFully(),例如:

ByteStreams.skipFully(tmpStream, range.start());
tmpStream = ByteStreams.limit(tmpStream, range.length());

答案 5 :(得分:2)

除了this解决方案,使用skip的{​​{1}}方法,您还可以读取从文件中间开始的范围。

InputStream

答案 6 :(得分:0)

我的项目遇到了类似的问题,你可以在这里查看工作代码PartInputStream。 我用它来资产和文件输入流。但它不适合最初不可用的流,例如网络流。