Hi Chris,
There is some duplication in the descriptions of the buffer contents;
see below.
On 5/1/2015 5:54 AM, Chris Hegarty wrote:
This latest version addresses all comments so far:
/**
* 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,
end
* of stream is detected, or an exception is thrown. 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. _
This section duplicates the previous sentence and the following sentence.
*
* <p> In the case where {@code off > 0}, elements {@code b[0]} through
* {@code b[off-1]} are unaffected. In every case, elements
* {@code b[off+len]} through {@code b[b.length-1]} are unaffected.
*
_ * <p> In every case, elements {@code b[0]} through {@code b[off-1]}
and __
__ * elements {@code b[off+len]} through {@code b[b.length-1]} are
unaffected. _
Duplicates previous paragraph.
Each section of the buffer should be described only once.
Regards, Roger
*
* <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 _occur _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.
*
* @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 readNBytes(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.
On 24/04/15 09:44, Chris Hegarty wrote:
On 23 Apr 2015, at 22:24, Roger Riggs <roger.ri...@oracle.com> wrote:
Hi Pavel,
On 4/23/2015 5:12 PM, Pavel Rappo wrote:
Hey Roger,
1. Good catch! This thing also applies to
java.io.InputStream.read(byte[], int, int):
Yes, good catch indeed.
* <p> In every case, elements <code>b[0]</code> through
* <code>b[off]</code> and elements <code>b[off+len]</code>
through
* <code>b[b.length-1]</code> are unaffected.
I suppose the javadoc for the method proposed by Chris has started
its life as a
copy of the javadoc read(byte[], int, int) which was assumed to be
perfectly
polished. Unfortunately it was a false assumption.
it happens... many many people have read those descriptions (or
didn't because
it was too obvious or thought to be redundant).
I propose this small amendment.
* <p> In the case where {@code off > 0}, elements {@code b[0]} through
* {@code b[off-1]} are unaffected. In every case, elements
* {@code b[off+len]} through {@code b[b.length-1]} are unaffected.
2. About awkward sentences. This paragraph also has to be rephrased
for the same reason:
* <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.
If k == 0 then spec claims to store values in b[off]... b[off - 1].
Reading the whole method description leads to be believe that 'k'
cannot equal 0 at this point. The previous paragraph handles the case
where len is 0. The previous paragraph to that handles the EOF case.
This paragraph implicitly implies that k is greater than 0, “The
first byte read”, and “the number of actual bytes read”, neither of
which can be 0 at this point.
I included below [*] the latest version of this method, including all
comments so far.
If one concludes that's an empty interval then its ok; it just reads
oddly and can
make the reader think its wrong.
In some cases it is easier if the upper bound is defined to be
exclusive.
Then if lower == upper, its empty.
If better language were constructed for the new method then perhaps
it could
be worked back into methods with similar behavior later. If the
wording changes
in any significant way, the conformance team will have to go back
and re-evaluate
it in detail to see if it really has changed. So I'd leave it alone.
Roger
-Chris.
[*]
/**
* 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, end
* of stream is detected, or an exception is thrown. 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 the case where {@code off > 0}, elements {@code b[0]} through
* {@code b[off-1]} are unaffected. In every case, elements
* {@code b[off+len]} through {@code b[b.length-1]} are unaffected.
*
* <p> In every case, elements {@code b[0]} through {@code b[off-1]}
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, 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.
*
* @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 readNBytes(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;
}