JDK-6204246 : InputStream.skip(long n) should not skip fewer bytes than min(n, available())
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2004-12-04
  • Updated: 2012-01-11
  • Resolved: 2005-10-04
Related Reports
Duplicate :  
Description
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

Comments
EVALUATION The spec for InputStream.available() was modified by bug 4711604. In that fix, we weaken the implication that InputStream.skip() will be able to skip at least the number of bytes reported by available(). In the case of BufferedInputStream, the reason that skip() can not necessarily skip over more bytes than the buffer size is that it must support the semantics of reset().
04-10-2005