Java: input label restriction

According to the Java documentation , the readlimit parameter of the label method on the Class InputStream server is set to "the maximum byte limit that can be read before the label position becomes invalid.". I have a file called sample.txt whose content is "hello". And I wrote this code:

import java.io.*; public class InputStream{ public static void main (String[] args) throws IOException { InputStream reader = new FileInputStream("sample.txt"); BufferedInputStream bis = new BufferedInputStream(reader); bis.mark(1); bis.read(); bis.read(); bis.read(); bis.read(); bis.reset(); System.out.println((char)bis.read()); } } 

The output is "h". But if I read more than one byte after the label method, should I not get an error for invalid calling the reset method?

+7
source share
4 answers

I would put this on a documentation error.

The nonparametric doc for BufferedInputStream is “See the General InputStream Label Method Contract”, which for me indicates that the BufferedInputStream behaves differently despite the absence of the doc parameter.

And the general contract, as indicated by InputStream , is

The readlimit arguments indicate this input stream, which allows many bytes to be considered before the label position is invalidated [...], the stream does not need to store any data at all if more is read from the stream than reading bytes of bytes

In other words, readlimit is a sentence; flow is free to promise and overload.

+5
source

If you look at the source , in particular the fill () method, you can see (after a while!) That this only invalidates, note when absolutely necessary, i.e. it is more tolerant than documentation can offer.

 ... else if (pos >= buffer.length) /* no room left in buffer */ if (markpos > 0) { /* can throw away early part of the buffer */ int sz = pos - markpos; System.arraycopy(buffer, markpos, buffer, 0, sz); pos = sz; markpos = 0; } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ .... 

The default buffer size is relatively large (8K), so invalidation will not be activated in your example.

+2
source

Considering the implementation of BufferedInputStream , he describes the significance of the marker position in JavaDocs (the markpos protected field):

[ markpos is] the value of the pos field during the call to the last mark method.

This value is always in the range -1 to pos . If there is no marked position in the input stream, this field is -1 . If there is a marked position in the input stream, then buf[markpos] is the first byte that will be served as input after the reset operation. If markpos not -1 , then all bytes from the positions buf[markpos] through buf[pos-1] must remain in the buffer array (although they can be moved to another location in the buffer array with the appropriate settings for the count , pos and markpos ); they cannot be discarded until the difference between pos and markpos exceeds marklimit .

Hope this helps. Take a look at the definitions of read , reset and the private fill method in the class to see how it all relates.

In short, only if the class receives more data to fill its buffer will the label position be taken into account. It will be invalidated correctly if more bytes are read than the mark call is allowed. As a result, read calls do not necessarily invoke the behavior declared in public JavaDoc comments.

+1
source

It looks like a subtle mistake. If you reduce the sizey buffer, you will get an IOException

 public static void main(String[] args) throws IOException { InputStream reader = new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5, 6, 7, 8}); BufferedInputStream bis = new BufferedInputStream(reader, 3); bis.mark(1); bis.read(); bis.read(); bis.read(); bis.read(); bis.reset(); System.out.println((char)bis.read()); } 
+1
source

All Articles