Sie müssen das in java.io
festgelegte Dekorationsmuster befolgen, um dies zu implementieren.
wir es versuchen hier:
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;
}
}
Die Inputstreams sollen Faden sicher sein, so dass Konten für die liberale Verwendung der Synchronisation. Ich spielte mit volatile
und AtomicLong
Position Variablen, aber die Synchronisation ist wahrscheinlich am besten, weil es einem Thread erlaubt, auf dem Strom zu operieren und seine Position abzufragen, ohne die Sperre aufzugeben.
PositionInputStream is = …
synchronized (is) {
is.read(buf);
pos = is.getPosition();
}
Dekorierermuster eine schöne Lösung für dieses ist, es stimmen oben. Eine Option wäre, synchronisierte Dokumente zu entfernen und zu dokumentieren, dass die Implementierung nicht Thread-sicher ist. Ein Aufrufer, der read() liest und dann die Position überprüft, muss sich trotzdem synchronisieren, um ein brauchbares (atomares) Verhalten zu erreichen. – volley
Ich glaube nicht, dass irgendjemand von einer bereits existierenden Implementierung weiß? Es scheint, als würde das NIH-Syndrom eine sehr häufige Anforderung neu implementieren. –
Ich mag die Idee und es ist leicht zu einer Anwendung steckbar. Es gibt jedoch ein schwerwiegendes Problem, über das Benutzer dieser Klasse Bescheid wissen sollten: Wenn ein gepufferter Leser diese Klasse verwendet, ist die gemeldete Position falsch, da die Daten in Buckets und nicht Byte für Byte gelesen werden. – Asterios