给定 Java InputStream,如何确定流中的当前偏移量?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/240294/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 11:35:08  来源:igfitidea点击:

Given a Java InputStream, how can I determine the current offset in the stream?

javaioinputstream

提问by Chris R

I'd like something like a generic, re-usable getPosition()method that will tell me the number of bytes read from the starting point of the stream. Ideally, I would prefer this to work with all InputStreams, so that I don't have to wrap each and every one of them as I get them from disparate sources.

我想要一个通用的、可重用的getPosition()方法,它会告诉我从流的起点读取的字节数。理想情况下,我希望它与所有 InputStreams 一起使用,这样我就不必在从不同的来源获取它们时将它们中的每一个都包装起来。

Does such a beast exist? If not, can anyone recommend an existing implementation of a counting InputStream?

这样的野兽存在吗?如果没有,有人可以推荐一个计数的现有实现InputStream吗?

回答by erickson

You'll need to follow the Decorator pattern established in java.ioto implement this.

您需要遵循中建立的装饰器模式java.io来实现这一点。

Let's give it a try here:

让我们在这里试一试:

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

public final class PositionInputStream
  extends FilterInputStream
{

  private long pos = 0;

  private long mark = 0;

  public PositionInputStream(InputStream in)
  {
    super(in);
  }

  /**
   * <p>Get the stream position.</p>
   *
   * <p>Eventually, the position will roll over to a negative number.
   * Reading 1 Tb per second, this would occur after approximately three 
   * months. Applications should account for this possibility in their 
   * design.</p>
   *
   * @return the current stream position.
   */
  public synchronized long getPosition()
  {
    return pos;
  }

  @Override
  public synchronized int read()
    throws IOException
  {
    int b = super.read();
    if (b >= 0)
      pos += 1;
    return b;
  }

  @Override
  public synchronized int read(byte[] b, int off, int len)
    throws IOException
  {
    int n = super.read(b, off, len);
    if (n > 0)
      pos += n;
    return n;
  }

  @Override
  public synchronized long skip(long skip)
    throws IOException
  {
    long n = super.skip(skip);
    if (n > 0)
      pos += n;
    return n;
  }

  @Override
  public synchronized void mark(int readlimit)
  {
    super.mark(readlimit);
    mark = pos;
  }

  @Override
  public synchronized void reset()
    throws IOException
  {
    /* A call to reset can still succeed if mark is not supported, but the 
     * resulting stream position is undefined, so it's not allowed here. */
    if (!markSupported())
      throw new IOException("Mark not supported.");
    super.reset();
    pos = mark;
  }

}

The InputStreams are intended to be thread safe, so that accounts for the liberal use of synchronization. I played around with volatileand AtomicLongposition variables, but synchronization is probably best because it allows one thread to operate on the stream and query its position without relinquishing the lock.

InputStreams 旨在是线程安全的,因此可以自由使用同步。我玩过volatileAtomicLong定位变量,但同步可能是最好的,因为它允许一个线程对流进行操作并查询其位置,而无需放弃锁定。

PositionInputStream is = …
synchronized (is) {
  is.read(buf);
  pos = is.getPosition();
}

回答by Joe Liversedge

Take a look at CountingInputStreamin the Commons IO package. They have a pretty good collection of other useful InputStream variants as well.

查看Commons IO 包中的CountingInputStream。他们也有很多其他有用的 InputStream 变体。

回答by Vadzim

回答by sblundy

No. InputStreamis intended to handle potentially infinite amounts of data, so a counter would get in the way. In addition to wrapping them all, you might be able to do something with aspects.

No.InputStream旨在处理潜在的无限数量的数据,因此计数器会妨碍。除了将它们全部包装起来之外,您还可以对方面做一些事情。