--- old/src/java.base/share/classes/java/io/InputStream.java 2018-10-23 14:56:28.000000000 -0700 +++ new/src/java.base/share/classes/java/io/InputStream.java 2018-10-23 14:56:27.000000000 -0700 @@ -64,8 +64,8 @@ *

While the stream is open, the {@code available()}, {@code read()}, * {@code read(byte[])}, {@code read(byte[], int, int)}, * {@code readAllBytes()}, {@code readNBytes(byte[], int, int)}, - * {@code readNBytes(int)}, {@code skip(long)}, and - * {@code transferTo()} methods all behave as if end of stream has been + * {@code readNBytes(int)}, {@code skip(long)}, {@code skipNBytes(long)}, + * and {@code transferTo()} methods all behave as if end of stream has been * reached. After the stream has been closed, these methods all throw * {@code IOException}. * @@ -139,6 +139,14 @@ } @Override + public void skipNBytes(long n) throws IOException { + ensureOpen(); + if (n > 0) { + throw new EOFException(); + } + } + + @Override public long transferTo(OutputStream out) throws IOException { Objects.requireNonNull(out); ensureOpen(); @@ -496,6 +504,44 @@ } /** + * Reads and discards up to {@code n} bytes of data from this input + * stream. If {@code n <= 0}, no bytes are skipped. An + * {@code EOFException} may optionally be thrown if end of stream is + * encountered before the requested number of bytes has been skipped. + * + *

This method blocks until data is available to skip, end of file is + * detected, or an exception is thrown. + * + * @param n the number of bytes to be skipped. + * @return the actual number of bytes skipped which might be zero. + * @throws EOFException if {@code throwOnEOF} is {@code true} and end + * of stream is encountered before {@code n} bytes are skipped. + * @throws IOException if an I/O error occurs. + */ + private long discardNBytes(long n, boolean throwOnEOF) throws IOException { + if (n <= 0) { + return 0; + } + + long remaining = n; + int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining); + byte[] skipBuffer = new byte[size]; + + while (remaining > 0) { + int nr = read(skipBuffer, 0, (int)Math.min(size, remaining)); + if (nr < 0) { + if (throwOnEOF) { + throw new EOFException(); + } + break; + } + remaining -= nr; + } + + return n - remaining; + } + + /** * Skips over and discards n bytes of data from this input * stream. The skip method may, for a variety of reasons, end * up skipping over some smaller number of bytes, possibly 0. @@ -513,29 +559,37 @@ * For instance, the implementation may depend on the ability to seek. * * @param n the number of bytes to be skipped. - * @return the actual number of bytes skipped. + * @return the actual number of bytes skipped which might be zero. * @throws IOException if an I/O error occurs. */ public long skip(long n) throws IOException { + return discardNBytes(n, false); + } - long remaining = n; - int nr; - - if (n <= 0) { - return 0; - } - - int size = (int)Math.min(MAX_SKIP_BUFFER_SIZE, remaining); - byte[] skipBuffer = new byte[size]; - while (remaining > 0) { - nr = read(skipBuffer, 0, (int)Math.min(size, remaining)); - if (nr < 0) { - break; + /** + * Skips over and discards exactly {@code n} bytes of data from this input + * stream. If {@code n <= 0}, no bytes are skipped. If {@code n > 0}, + * then {@code n} bytes of data are skipped unless end of stream is + * encountered first, in which case an {@code EOFException} is thrown. + * + *

This method blocks until data is available to skip, end of file is + * detected, or an exception is thrown. + * + * @param n the number of bytes to be skipped. + * @throws EOFException if end of stream is encountered before {@code n} + * bytes are skipped. + * @throws IOException if an I/O error occurs. + */ + public void skipNBytes(long n) throws IOException { + if (n > 0) { + // Invoke skip() so as to avail of any subclass efficiency + long ns = skip(n); + + // If not enough skipped, read and discard bytes, failing on EOF + if (ns != n) { + discardNBytes(n - ns, true); } - remaining -= nr; } - - return n - remaining; } /**