Pergunta

Eu gostaria de algo como um genérico, reutilizável getPosition() Método que me dirá o número de bytes lidos no ponto de partida do fluxo. Idealmente, eu preferiria que isso funcione com todos os fluxos de entrada, para não precisar embrulhar cada um deles, pois os obtém de fontes díspares.

Esse animal existe? Caso contrário, alguém pode recomendar uma implementação existente de uma contagem InputStream?

Foi útil?

Solução

Dar uma olhada em ContingInputStream no pacote do Commons. Eles também têm uma boa coleção de outras variantes de entrada úteis.

Outras dicas

Você precisará seguir o padrão de decorador estabelecido em java.io Para implementar isso.

Vamos tentar aqui:

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

}

Os InsputStreams devem ser seguros, de modo que expliquem o uso liberal da sincronização. Eu brinquei com volatile e AtomicLong Posicionar variáveis, mas a sincronização é provavelmente melhor porque permite que um thread opere no fluxo e consulte sua posição sem renunciar à trava.

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

Não. InputStream destina -se a lidar com quantidades potencialmente infinitas de dados, portanto, um contador atrapalharia. Além de envolver todos eles, você poderá fazer algo com aspectos.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top