Wann kann DataInputStream.skipBytes(n) nicht n Bytes überspringen?
Frage
Der Sun-Dokumentation für DataInput.skipBytes gibt an, dass es „versucht, n Datenbytes aus dem Eingabestream zu überspringen und dabei die übersprungenen Bytes zu verwerfen“.Es kann jedoch sein, dass eine kleinere Anzahl von Bytes, möglicherweise Null, übersprungen wird.Dies kann auf eine Reihe von Bedingungen zurückzuführen sein;Das Erreichen des Dateiendes, bevor n Bytes übersprungen wurden, ist nur eine Möglichkeit.“
Abgesehen davon, dass das Ende der Datei erreicht wurde, warum?
skipBytes()
nicht die richtige Anzahl an Bytes überspringen?(DerDataInputStream
Ich verwende entweder ein WrappingFileInputStream
oder einPipedInputStream
.)Wenn ich auf jeden Fall n Bytes überspringen und ein werfen möchte
EOFException
Wenn dies dazu führt, dass ich zum Ende der Datei gehe, sollte ich verwendenreadFully()
und das resultierende Byte-Array ignorieren?Oder gibt es einen besseren Weg?
Lösung
1) Es stehen möglicherweise nicht so viele Daten zum Lesen zur Verfügung (das andere Ende der Pipe hat möglicherweise noch nicht so viele Daten gesendet), und die implementierende Klasse ist möglicherweise nicht blockierend (d. h.es gibt einfach das zurück, was es kann, anstatt auf genügend Daten zu warten, um die Anfrage zu erfüllen.
Ich weiß jedoch nicht, ob sich Implementierungen tatsächlich so verhalten, aber die Schnittstelle ist so konzipiert, dass sie dies zulässt.
Eine andere Möglichkeit besteht einfach darin, die Datei während des Lesevorgangs zu schließen.
2) Entweder readFully() (das immer auf genügend Eingaben wartet oder sonst fehlschlägt) oder SkipBytes() in einer Schleife aufrufen.Ich denke, Ersteres ist wahrscheinlich besser, es sei denn, die Auswahl ist wirklich riesig.
Andere Tipps
Ich bin heute auf dieses Problem gestoßen.Es wurde eine Netzwerkverbindung auf einer virtuellen Maschine abgelesen, daher kann ich mir vorstellen, dass es dafür mehrere Gründe geben könnte.Ich habe es gelöst, indem ich einfach den Eingabestream gezwungen habe, Bytes zu überspringen, bis er die Anzahl an Bytes übersprungen hat, die ich wollte:
int byteOffsetX = someNumber; //n bytes to skip
int nSkipped = 0;
nSkipped = in.skipBytes(byteOffsetX);
while (nSkipped < byteOffsetX) {
nSkipped = nSkipped + in.skipBytes(byteOffsetX - nSkipped);
}
Josh Bloch hat dies kürzlich veröffentlicht.Es ist konsistent, dass InputStream.read nicht garantiert so viele Bytes liest, wie es könnte.Als API-Methode ist es jedoch völlig sinnlos.InputStream sollte wahrscheinlich auch readFully haben.
Es stellt sich heraus, dass readFully() mehr Leistungsaufwand verursacht, als ich in Kauf nehmen wollte.
Am Ende bin ich einen Kompromiss eingegangen:Ich rufe einmal skipBytes() auf, und wenn das weniger als die richtige Anzahl an Bytes zurückgibt, rufe ich readFully() für die verbleibenden Bytes auf.