Peter,
Ah, good point. Do we really need a new Exception type for this, is this
information really that useful? How can you recover?
What if this error condition was better cover in the API.
* <p> If an I/O error occurs reading from the input stream, then it may do
* so after some, but not all, bytes of {@code b} have been updated with
* data from the input stream. Consequently the input stream and {@code b}
* may be in an inconsistent state. It is strongly recommended that the
* stream be promptly closed if an I/O error occurs.
-Chris.
On 23 Apr 2015, at 15:20, Peter Levart <[email protected]> wrote:
> Hi Chris,
>
> Currently InputStream guarantees that either some bytes are read *xor* EOF
> (-1) is returned *xor* IOException is thrown. Even with default
> implementation of read(byte[], int, int) which is implemented in terms of int
> read(). This new method can throw IOException after some bytes have
> successfully been read from stream and the caller does not get to know how
> many. Would something like the following make any more sense?
>
> public int readBytes(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;
> try {
> count = read(b, off + n, len - n);
> } catch (IOException e) {
> if (n == 0) {
> throw e;
> } else {
> throw new IncompleteReadBytesException(e, n);
> }
> }
> if (count < 0)
> break;
> n += count;
> }
> return n;
> }
>
> /**
> * Thrown from {@link #readBytes(byte[], int, int)} when at least one byte
> * has successfully been read from stream into the byte buffer when
> IOException
> * was thrown.
> */
> public static class IncompleteReadBytesException extends IOException {
> private final int bytesRead;
>
> public IncompleteReadBytesException(IOException cause, int bytesRead)
> {
> super(cause);
> this.bytesRead = bytesRead;
> }
>
> /**
> * @return number of bytes read successfully from stream into byte
> array
> * before exception was thrown.
> */
> public int getBytesRead() {
> return bytesRead;
> }
> }
>
>
> Regards, Peter
>
>
> On 04/23/2015 11:01 AM, Chris Hegarty wrote:
>> A while back when we added the long overdue java.io.InputStream.transferTo
>> method, there was support for adding a blocking bulk read operation. This
>> has been sitting in a branch in the sandbox since then. I would like to
>> revive it with the intention of bringing it into 9. The motivation for this
>> addition is provide library support for a common pattern found when reading
>> from input streams.
>>
>> /**
>> * Reads some bytes from the input stream into the given byte array. This
>> * method blocks until {@code len} bytes of input data have been read, or
>> * end of stream is detected. The number of bytes actually read, possibly
>> * zero, is returned. This method does not close the input stream.
>> *
>> * <p> In the case where end of stream is reached before {@code len} bytes
>> * have been read, then the actual number of bytes read will be returned.
>> * When this stream reaches end of stream, further invocations of this
>> * method will return zero.
>> *
>> * <p> If {@code len} is zero, then no bytes are read and {@code 0} is
>> * returned; otherwise, there is an attempt to read up to {@code len} bytes.
>> *
>> * <p> The first byte read is stored into element {@code b[off]}, the next
>> * one in to {@code b[off+1]}, and so on. The number of bytes read is, at
>> * most, equal to {@code len}. Let <i>k</i> be the number of bytes actually
>> * read; these bytes will be stored in elements {@code b[off]} through
>> * {@code b[off+}<i>k</i>{@code -1]}, leaving elements {@code b[off+}<i>k</i>
>> * {@code ]} through {@code b[off+len-1]} unaffected.
>> *
>> * <p> In every case, elements {@code b[0]} through {@code b[off]} and
>> * elements{@code b[off+len]} through {@code b[b.length-1]} are unaffected.
>> *
>> * <p> The behavior for the case where the input stream is <i>asynchronously
>> * closed</i>, or the thread interrupted during the read, is highly input
>> * stream specific, and therefore not specified.
>> *
>> * <p> If an I/O error occurs reading from the input stream, then it may do
>> * so after some bytes have been read. Consequently the input stream may be
>> * in an inconsistent state. It is strongly recommended that the stream be
>> * promptly closed if an I/O error occurs.
>> *
>> * @param b the buffer into which the data is read
>> * @param off the start offset in {@code b} at which the data is written
>> * @param len the maximum number of bytes to read
>> * @return the actual number of bytes read into the buffer
>> * @throws IOException if an I/O error occurs
>> * @throws NullPointerException if {@code b} is {@code null}
>> * @throws IndexOutOfBoundsException If {@code off} is negative, {@code len}
>> * is negative, or {@code len} is greater than {@code
>> b.length - off}
>> *
>> * @since 1.9
>> */
>> public int readBytes(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;
>> }
>>
>> -Chris.
>>
>