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

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

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

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

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

正如danben所说 ,只需装饰您的流并强制执行约束:

 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 } 

考虑使用http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/io/LimitInputStream.html

如果你只需要100个字节,那么simple可能是最好的,我将它们读入一个数组并将其包装为ByteArrayInputStream。 例如

  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()方法更好的性能。

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

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

除了这个解决方案,使用InputStreamskip方法,您还可以读取从文件中间开始的范围。

 public class RangeInputStream extends InputStream { private InputStream parent; private long remaining; public RangeInputStream(InputStream parent, long start, long end) throws IOException { if (end < start) { throw new IllegalArgumentException("end < start"); } if (parent.skip(start) < start) { throw new IOException("Unable to skip leading bytes"); } this.parent=parent; remaining = end - start; } @Override public int read() throws IOException { return --remaining >= 0 ? parent.read() : -1; } } 

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