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

发布于 2024-07-08 03:30:08 字数 182 浏览 5 评论 0原文

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

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

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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

拥醉 2024-07-15 03:30:08

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

让我们在这里尝试一下:

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;
  }

}

InputStreams 旨在是线程安全的,因此可以考虑同步的自由使用。 我尝试了 volatileAtomicLong 位置变量,但同步可能是最好的,因为它允许一个线程在流上操作并查询其位置而不放弃锁定。

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

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

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 volatile and AtomicLong position variables, but synchronization is probably best because it allows one thread to operate on the stream and query its position without relinquishing the lock.

PositionInputStream is = …
synchronized (is) {
  is.read(buf);
  pos = is.getPosition();
}
偏爱自由 2024-07-15 03:30:08

查看 CountingInputStream 中的公共 IO 包。 他们还收集了很多其他有用的 InputStream 变体。

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

信仰 2024-07-15 03:30:08

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

No. InputStream is 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文