I've noticed that the clojure.java.io
namespace's code includes a very common mistake when reading InputStreams. Your typical do-copy
will have some variation of this loop:
`
(let [buffer (make-array Byte/TYPE (buffer-size opts))]
(loop []
(let [size (.read input buffer)]
(when (pos? size)
(do (.write output buffer 0 size)
(recur))))))
`
It is incorrect to say when (pos? size)
because the InputStream interface has this definition for read method 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.
Yes, it is perfectly legal for read
to return 0 bytes read when the stream is not at the end yet.
I guess they made it like that so that you can return 0 bytes from a socket that is stalled and enable the caller to timeout or abort or do something else.
In any case the correct condition for detecting end of stream is to compare the return to -1
.