Domanda

Vorrei qualcosa come un metodo generico, riutilizzabile getPosition () che mi dirà il numero di byte letti dal punto iniziale dello stream. Idealmente, preferirei che questo funzionasse con tutti gli InputStreams, in modo da non doverli avvolgere tutti mentre li ottengo da fonti disparate.

Esiste una tale bestia? In caso contrario, qualcuno può raccomandare un'implementazione esistente di un conteggio InputStream ?

È stato utile?

Soluzione

Dai un'occhiata a CountingInputStream nel pacchetto IO IO. Hanno anche una buona collezione di altre utili varianti di InputStream.

Altri suggerimenti

Per implementarlo dovrai seguire il modello Decorator stabilito in java.io .

Proviamo qui:

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

}

Gli InputStreams sono pensati per essere thread-safe, in modo da rendere conto dell'uso liberale della sincronizzazione. Ho giocato con le variabili di posizione volatile e AtomicLong , ma la sincronizzazione è probabilmente la migliore perché consente a un thread di operare sullo stream e di interrogare la sua posizione senza rinunciare al blocco.

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

No. InputStream ha lo scopo di gestire quantità potenzialmente infinite di dati, quindi un contatore si frappone. Oltre a racchiuderli tutti, potresti essere in grado di fare qualcosa con gli aspetti.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top