Robust skipping of data in a java.io.InputStream and its subtypes
I don't think we can get a really robust implementation because the skip()
method contract is rather bizarre. For one thing, the behaviour at EOF
is not well defined. If I want to skip 8 bytes and is.skip(8)
returns 0
, it's not trivial to decide if I should try again, there is a danger of an infinite loop if some implementation chooses to return 0
at EOF
. And available()
is not to be trusted, either.
Hence, I propose the following:
/**
* Skips n bytes. Best effort.
*/
public static void myskip(InputStream is, long n) throws IOException {
while(n > 0) {
long n1 = is.skip(n);
if( n1 > 0 ) {
n -= n1;
} else if( n1 == 0 ) { // should we retry? lets read one byte
if( is.read() == -1) // EOF
break;
else
n--;
} else // negative? this should never happen but...
throw new IOException("skip() returned a negative value. This should never happen");
}
}
Shouldn't we return a value to inform the number of bytes "really skipped"? Or a boolean to inform that EOF was reached? We cannot do that in a robust way. For example, if we call skip(8)
for a FileInputStream
object, it will return 8 even if we are at EOF
, or if the file has only 2 bytes. But the method is robust in the sense that it does what we want to: skip n
bytes (if possible) and let me continue processing it (if my next read returns -1
I'll know that EOF
was reached).
This seems to be working for skipping n
bytes:
long skippedTotal = 0;
while (skippedTotal != n) {
long skipped = _stream.skip(n - skippedTotal);
assert(skipped >= 0);
skippedTotal += skipped;
if (skipped == 0)
break;
}
boolean skippedEnough = skippedTotal == n;
However it's not clear that it will work for all implementations of InputStream
that could be passed to my library. I'm wondering whether implementing my own buffered skip method is the way to go.