Bill Pugh writes:
There is a bug in java.io.InputStream.skip().
Stuff related to this has been reported before, but I think we can make
a strong
case that the behavior I'm reporting is a bug that needs to be fixed.
The spec for InputStream.available() says:
>> Returns the number of bytes that can be read (or skipped over) from
>> this input stream without blocking by the next caller of a method for
>> this input stream.
However, BufferedInputStream.skip(long) can decide to skip less than
the number
of bytes that were reported as being available to skip.
Here is a test case:
public class SkipBug {
public static void main(String args[]) throws IOException {
int bufferSize = 20;
int skipRequestSize = bufferSize;
ByteArrayInputStream bytes = new ByteArrayInputStream(new byte
[bufferSize*10]);
BufferedInputStream buffered = new BufferedInputStream(bytes,
bufferSize);
buffered.read();
int avail = buffered.available();
long skipped = buffered.skip(skipRequestSize);
assert skipped >= Math.min(skipRequestSize, avail)
: "Skipped only " + skipped + " bytes but "
+ avail + " were available";
}
}
The call to available will report that 199 bytes are available to skip,
but the call to skip 20 bytes will only skip 19.
There is a fair bit of code that depends on being able to read or skip
as many
bytes as are returned by available(), and that doesn't work for
BufferedInputStream and skip().
I think the spec for InputStream should be clarified to say that it is
intended/desirable/required that read(byte[], int, int) and skip(long)
will not read/skip over fewer bytes
than are available unless fewer bytes than that are requested. The spec
for available() clearly seems to imply this.
In others words,
min(bytes available, bytes requested) <= bytes read/skipped <= bytes
requested
Note that if an InputStream.available() returns 0, this has no impact.
This is related to bug 4254082
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4254082
but that bug doesn't mention available().
We've actually got a bug detector in FindBugs that flags all uses of
skip where the return value is not checked on a BufferedInputStream due
to this flaw in the Java i/o libraries.
I'd like to be able to change that so it doesn't warn about cases in
which the programmer
has checked available().
###@###.### 2004-12-04 22:18:38 GMT