java - globales - importancia del desplazamiento forzado
Dado un Java InputStream, ¿cómo puedo determinar el desplazamiento actual en la secuencia? (4)
Deberá seguir el patrón Decorator establecido en java.io
para implementar esto.
Démosle una oportunidad aquí:
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;
}
}
Los InputStreams están destinados a ser seguros para subprocesos, por lo que las cuentas para el uso liberal de la sincronización. AtomicLong
variables de posición volatile
y AtomicLong
, pero la sincronización es probablemente la mejor porque permite que un subproceso opere en la secuencia y consulte su posición sin renunciar al bloqueo.
PositionInputStream is = …
synchronized (is) {
is.read(buf);
pos = is.getPosition();
}
Me gustaría algo como un método getPosition()
genérico y reutilizable que me dirá el número de bytes leídos desde el punto de inicio de la transmisión. Idealmente, preferiría que esto funcione con todos los InputStreams, de modo que no tenga que envolver todos y cada uno de ellos, ya que los obtengo de fuentes dispares.
existe tal bestia? Si no, ¿alguien puede recomendar una implementación existente de un conteo de InputStream
?
Eche un vistazo a CountingInputStream en el paquete Commons IO. También tienen una buena colección de otras variantes útiles de InputStream.
No. InputStream
está diseñado para manejar cantidades de datos potencialmente infinitas, por lo que un contador se interpondrá en el camino. Además de envolverlos a todos, es posible que puedas hacer algo con aspectos.
También está CountingInputStream
en Guava .
Apidocs: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/io/CountingInputStream.html
Fuente: https://github.com/google/guava/blob/master/guava/src/com/google/common/io/CountingInputStream.java