Can BufferedInputStream.read(byte[] b, int off, int len) ever return 0? Are there significant, broken InputStreams that might cause this?

 ̄綄美尐妖づ 提交于 2020-02-24 04:24:12

问题


Is it ever possible for BufferedInputStream(byte[] b, int off, int len) to return 0?

READER'S DIGEST VERSION (you can read the rest below, for context, but I think it boils down to this:) Are there InputStreams (i.e. SocketInputStream, CipherInputStream, etc. in the JDK or in commonly used libraries (i.e. Apache Commons, Guava), that don't correctly honor the contract of InputStream.read(byte[],off,len) and might return '0' even if len != 0?


(Note 1: my interest is whether it can really happen in code that uses just the JDK, or maybe a few really common Java libraries, such as Apache Commons; I am looking at the javadoc for clue, but I am also looking at the source for BufferedInputStream (Java 7, in case it matters) in case some edge case is not documented correctly -- and I'm not fully convinced one way or another, thus my question)

(Note 2: I don't mean in the trivial case, where len==0, I mean in the general case, where you pass in a non-zero array, can you ever get back 0 bytes?)

The javadoc is here and it says, in part:

This method implements the general contract of the *corresponding* [my emphasis added] read method of the InputStream class. As an additional convenience, it attempts to read as many bytes as possible by repeatedly invoking the read method of the underlying stream. This iterated read continues until one of the following conditions becomes true:

[two irrelevant conditions omitted]

- The available method of the underlying stream returns zero, indicating that further input requests would block.

And then the doc for the return value says:

Returns: the number of bytes read, or -1 if the end of the stream has been reached.

So: by my reading of this, it's possible that when you call this read function, if no data is buffered and no data is available from the underlying InputStream (say, from a stalled http transfer,) then the read method should return 0, since 0 bytes were read.

and yet… a bunch of folks who seem to know more about this than me seem to believe that this read method will always return EOF or at least one byte.

So, I looked further into InputStream, to see what the general contract of the corresponding read method of the InputStream class really means, and I found this:

If len is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b.

So, according to the javadocs, I think this means BufferedInputStream should not return a 0. If I were looking only at the docs, I think I would be done now.

But: upon inspection, it seems to me that the implementation of BufferedInputStream doesn't really guarantee one byte or more bytes; it inherits this guarantee by depending on correct behavior of the underlying InputStream. The source for the abstract InputStream seems to get this guarantee correct (I think it can only return 0 bytes if len==0) but I don't know if this is true for all input streams in the JDK, let alone all input streams anywhere.

So. I think where I am so far is: BufferedInputStream will never return 0 unless the wrapped InputStream doesn't honor this guarantee of 1 or more bytes -- but I don't know how common this is.

1) Is my general analysis correct?

2) does anybody know of significant cases where InputStreams can return 0? (i.e. InputStreams that may return 0 with a non-zero len, so that if you wrap them in a BufferedInputStream, you need to guard against a zero return value? -- not somebody's personal, broken code, but important cases to watch out for, say in the JDK or Apache Commons or something.)

Apologies for the long question; I was doing more research as I wrote this, so the question grew.

NOTE: for context: I'm posting this question because I didn't understand a conversation I had in reference to this other question (Socket reading using BufferedInputStream) -- it might help to read that question for background.


回答1:


You didn’t read the spec of BufferedInputStream carefully enough. You cited:

This iterated read continues until one of the following conditions becomes true:

[two irrelevant conditions omitted]

  • The available method of the underlying stream returns zero, indicating that further input requests would block.

The BufferedInputStream will fulfill the contract of read reading at least one byte by directly delegating to the underlying stream for the first read. If the underlying stream correctly reads at least one byte for that first read, the contract has been fulfilled.

Only subsequent read attempts (the “iterated read”) are conditional, i.e. will be skipped if available returns 0 telling that another read attempt would block (again).


So the bottom line is that BufferedInputStream fulfills the contract, like all other JDK’s InputStreams — as far as I know. By the way, if you want to read an array entirely you can wrap the stream in a DataInputStream which offers a readFully method.



来源:https://stackoverflow.com/questions/21166196/can-bufferedinputstream-readbyte-b-int-off-int-len-ever-return-0-are-ther

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!