Avec un Java InputStream, comment puis-je déterminer le décalage actuel dans le flux?

StackOverflow https://stackoverflow.com/questions/240294

  •  04-07-2019
  •  | 
  •  

Question

Je voudrais quelque chose comme une méthode getPosition () générique et réutilisable qui me dira le nombre d'octets lus à partir du point de départ du flux. Idéalement, je préférerais que cela fonctionne avec tous les InputStreams, afin de ne pas avoir à envelopper chacun d'entre eux car je les obtiens de sources disparates.

Une telle bête existe-t-elle? Sinon, est-ce que quelqu'un peut recommander une implémentation existante d'un InputStream ?

Était-ce utile?

La solution

Jetez un coup d'œil à CountingInputStream dans le paquet IO Commons. Ils ont également une bonne collection d'autres variantes utiles de InputStream.

Autres conseils

Vous devez suivre le modèle de décorateur défini dans java.io pour le mettre en œuvre.

Essayons ici:

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

}

Les InputStreams sont conçus pour être thread-safe, ce qui explique l'utilisation généralisée de la synchronisation. J'ai joué avec les variables de position volatile et AtomicLong , mais la synchronisation est probablement préférable car elle permet à un thread d'opérer sur le flux et d'interroger sa position sans renoncer au verrou.

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

Non. InputStream est conçu pour gérer des quantités de données potentiellement infinies, de sorte qu'un compteur puisse vous gêner. En plus de les emballer tous, vous pourrez peut-être faire quelque chose avec des aspects.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top