RFR [9] Add blocking bulk read to java.io.InputStream

David M. Lloyd david.lloyd at redhat.com
Thu Apr 23 14:30:06 UTC 2015


I believe this is similar to how InterruptedIOException works, FWIW.

On 04/23/2015 09:20 AM, Peter Levart 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.
>

-- 
- DML



More information about the core-libs-dev mailing list