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 <peter.lev...@gmail.com> 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.
>> 
> 

Reply via email to