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. >> >