Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java: read vs readNBytes of the InputStream instance

In java, InputStream class has methods read(byte[], int, int) and readNBytes(byte[], int, int). It seems that these two methods have exactly the same functionality, so I wonder what are the differences between them.

like image 243
Y.S. Yuan Avatar asked Dec 13 '18 02:12

Y.S. Yuan


People also ask

What does InputStream read do in java?

read() reads next byte of data from the Input Stream. The value byte is returned in the range 0 to 255. If no byte is available because the end of the stream has been reached, the value -1 is returned.

Can we read InputStream twice in java?

Depending on where the InputStream is coming from, you might not be able to reset it. You can check if mark() and reset() are supported using markSupported() . If it is, you can call reset() on the InputStream to return to the beginning. If not, you need to read the InputStream from the source again.

What does InputStream read return?

Returns. the total number of bytes read into the buffer, or -1 if there is no more data because the end of the stream has been reached.

Why does InputStream read return an int?

It returns an int because when the stream can no longer be read, it returns -1. If it returned a byte, then -1 could not be returned to indicate a lack of input because -1 is a valid byte. In addition, you could not return value above 127 or below -128 because Java only handles signed bytes.


1 Answers

Edited for better visibility of discussion in the comments:

  • read() says it attempts to read "up to len bytes ... but a smaller number may be read. This method blocks until input data is available, end of file is detected, or an exception is thrown."
  • readNBytes() says "blocks until len bytes of input data have been read, end of stream is detected, or an exception is thrown."

Even though the JDK's implementation for InputStream is likely to give you identical results for both methods, the documented differences mean than other classes inheriting from it may behave differently.

E.g. Given the stream '12345<end>', read(s,0,10) is allowed to return '123', whereas readNbytes() is more likely to keep going to look for an end-of-stream and give you the whole thing.


Original answer:

You're right that the javadocs are very similar. When in doubt, always drop down to the source. Most IDEs make it easy to attach the OpenJDK source and lets you drill down to them.

This is readNBytes from InputStream.java:

public int readNBytes(byte[] b, int off, int len) throws IOException {
    Objects.requireNonNull(b);
    if (off < 0 || len < 0 || len > b.length - off)
        throw new IndexOutOfBoundsException();
    int n = 0;
    while (n < len) {
        int count = read(b, off + n, len - n);
        if (count < 0)
            break;
        n += count;
    }
    return n;
}

As you can see, it actually performs a call to read(byte[],int,int). The difference in this case is that if the actual read bytes is less than your specified len, it will attempt to read() again until it is confirmed that there is actually nothing left to be read.

Edit: Note that

  1. This is OpenJDK's implementation of the base InputStream. Others may differ.
  2. Subclasses of InputStream may also have their own overridden implementation. Consult the doc/source for the relevant class.
like image 61
NPras Avatar answered Nov 02 '22 13:11

NPras