代码之家  ›  专栏  ›  技术社区  ›  alex2k8

如何创建受约束的inputstream以只读文件的一部分?

  •  10
  • alex2k8  · 技术社区  · 14 年前

    我想创建一个只限于文件中特定字节范围的输入流,例如从0到100的字节。这样,一旦达到第100个字节,客户机代码就会看到EOF。

    7 回复  |  直到 7 年前
        1
  •  10
  •   rogerdpack    11 年前

    这个 read() 方法 InputStream 一次读取一个字节。你可以写一个子类 输入流 维护一个内部计数器;每次 读() 调用,更新计数器。如果已经达到最大值,则不允许进行任何进一步的读取(返回-1或类似的操作)。

    你还需要确保其他的阅读方法 read_int 不支持,etc(例如:重写它们并只抛出unsupportedOperationException());

    我不知道您的用例是什么,但是作为一个额外的好处,您可能也希望实现缓冲。

        2
  •  8
  •   Community rcollyer    7 年前

    AS 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
    }
    
        4
  •  2
  •   mdma    14 年前

    如果您只需要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 IOUtils.readFully 从ApacheCommonsIO,或者您可以显式地实现读循环。

    如果您有更高级的需求,例如从文件中间的段读取数据,或者读取更多的数据,那么扩展inputstream并重写read(byte[]、int、int)和read()将比重写read()方法提供更好的性能。

        5
  •  2
  •   petertc    10 年前

    你可以用番石榴的字节串。 请注意,您应该在限制之前使用skipfully(),例如:

    ByteStreams.skipFully(tmpStream, range.start());
    tmpStream = ByteStreams.limit(tmpStream, range.length());
    
        6
  •  2
  •   Community rcollyer    7 年前

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

    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;
        }
    }
    
        7
  •  0
  •   lexa-b    7 年前

    我的项目也解决了类似的问题,您可以在这里看到工作代码。 PartInputStream . 我将它用于资产和文件输入流。但它不适用于初始长度不可用的_°流,例如网络流。