Skip to content

Commit

Permalink
8247918: Clarify Reader.skip behavior for end of stream
Browse files Browse the repository at this point in the history
Reviewed-by: rriggs, naoto
  • Loading branch information
Brian Burkhalter committed Feb 19, 2021
1 parent 8a1c712 commit 7ffa148
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 69 deletions.
11 changes: 2 additions & 9 deletions src/java.base/share/classes/java/io/BufferedReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -397,14 +397,7 @@ public String readLine() throws IOException {
}

/**
* Skips characters.
*
* @param n The number of characters to skip
*
* @return The number of characters actually skipped
*
* @throws IllegalArgumentException If {@code n} is negative.
* @throws IOException If an I/O error occurs
* {@inheritDoc}
*/
public long skip(long n) throws IOException {
if (n < 0L) {
Expand Down
13 changes: 8 additions & 5 deletions src/java.base/share/classes/java/io/CharArrayReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -146,16 +146,19 @@ public int read(char b[], int off, int len) throws IOException {
}

/**
* Skips characters. Returns the number of characters that were skipped.
* Skips characters. If the stream is already at its end before this method
* is invoked, then no characters are skipped and zero is returned.
*
* <p>The {@code n} parameter may be negative, even though the
* {@code skip} method of the {@link Reader} superclass throws
* an exception in this case. If {@code n} is negative, then
* this method does nothing and returns {@code 0}.
*
* @param n The number of characters to skip
* @return The number of characters actually skipped
* @throws IOException If the stream is closed, or an I/O error occurs
* @param n {@inheritDoc}
*
* @return {@inheritDoc}
*
* @throws IOException {@inheritDoc}
*/
public long skip(long n) throws IOException {
synchronized (lock) {
Expand Down
8 changes: 5 additions & 3 deletions src/java.base/share/classes/java/io/FilterReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -76,9 +76,11 @@ public int read(char cbuf[], int off, int len) throws IOException {
}

/**
* Skips characters.
* {@inheritDoc}
*
* @throws IOException If an I/O error occurs
* @throws IllegalArgumentException If {@code n} is negative and the
* contained {@code Reader}'s {@code skip} method throws an
* IllegalArgumentException for a negative parameter
*/
public long skip(long n) throws IOException {
return in.skip(n);
Expand Down
15 changes: 2 additions & 13 deletions src/java.base/share/classes/java/io/LineNumberReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -267,18 +267,7 @@ public String readLine() throws IOException {
private char skipBuffer[] = null;

/**
* Skip characters.
*
* @param n
* The number of characters to skip
*
* @return The number of characters actually skipped
*
* @throws IOException
* If an I/O error occurs
*
* @throws IllegalArgumentException
* If {@code n} is negative
* {@inheritDoc}
*/
public long skip(long n) throws IOException {
if (n < 0)
Expand Down
12 changes: 2 additions & 10 deletions src/java.base/share/classes/java/io/PushbackReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -254,15 +254,7 @@ public void close() throws IOException {
}

/**
* Skips characters. This method will block until some characters are
* available, an I/O error occurs, or the end of the stream is reached.
*
* @param n The number of characters to skip
*
* @return The number of characters actually skipped
*
* @throws IllegalArgumentException If {@code n} is negative.
* @throws IOException If an I/O error occurs
* {@inheritDoc}
*/
public long skip(long n) throws IOException {
if (n < 0L)
Expand Down
4 changes: 3 additions & 1 deletion src/java.base/share/classes/java/io/Reader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -269,6 +269,8 @@ public int read(char cbuf[]) throws IOException {
/**
* Skips characters. This method will block until some characters are
* available, an I/O error occurs, or the end of the stream is reached.
* If the stream is already at its end before this method is invoked,
* then no characters are skipped and zero is returned.
*
* @param n The number of characters to skip
*
Expand Down
28 changes: 16 additions & 12 deletions src/java.base/share/classes/java/io/StringReader.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand Down Expand Up @@ -105,31 +105,35 @@ public int read(char cbuf[], int off, int len) throws IOException {
}

/**
* Skips the specified number of characters in the stream. Returns
* the number of characters that were skipped.
* Skips characters. If the stream is already at its end before this method
* is invoked, then no characters are skipped and zero is returned.
*
* <p>The {@code ns} parameter may be negative, even though the
* <p>The {@code n} parameter may be negative, even though the
* {@code skip} method of the {@link Reader} superclass throws
* an exception in this case. Negative values of {@code ns} cause the
* an exception in this case. Negative values of {@code n} cause the
* stream to skip backwards. Negative return values indicate a skip
* backwards. It is not possible to skip backwards past the beginning of
* the string.
*
* <p>If the entire string has been read or skipped, then this method has
* no effect and always returns 0.
* no effect and always returns {@code 0}.
*
* @throws IOException If an I/O error occurs
* @param n {@inheritDoc}
*
* @return {@inheritDoc}
*
* @throws IOException {@inheritDoc}
*/
public long skip(long ns) throws IOException {
public long skip(long n) throws IOException {
synchronized (lock) {
ensureOpen();
if (next >= length)
return 0;
// Bound skip by beginning and end of the source
long n = Math.min(length - next, ns);
n = Math.max(-next, n);
next += n;
return n;
long r = Math.min(length - next, n);
r = Math.max(-next, r);
next += r;
return r;
}
}

Expand Down
86 changes: 70 additions & 16 deletions test/jdk/java/io/Reader/Skip.java
@@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2021, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
Expand All @@ -22,29 +22,83 @@
*/

/* @test
@bug 4134311
@summary Test if skip works correctly
* @bug 4134311 8247918
* @summary Test if skip works correctly
* @run testng Skip
*/

import java.io.CharArrayReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.PushbackReader;
import java.io.RandomAccessFile;
import java.io.Reader;
import java.io.StringReader;


import java.io.*;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;

public class Skip {
public static void main(String argv[]) throws Exception {
File f = new File(System.getProperty("test.src", "."),
"SkipInput.txt");
FileReader fr = new FileReader(f);
try {
private static String FILENAME =
System.getProperty("test.src", ".") + File.separator + "SkipInput.txt";
private static File file = new File(FILENAME);

@Test
public void skip() throws IOException {
try (FileReader fr = new FileReader(file)) {
long nchars = 8200;
long actual = fr.skip(nchars);

if (actual > nchars) {
throw new Exception
("Should skip " + nchars + ", but skipped " +actual+" chars");
}
} finally {
fr.close();
Assert.assertFalse(actual > nchars,
"Should skip " + nchars + ", but skipped " +actual+" chars");
}
}

@DataProvider(name = "readers")
public Object[][] getReaders() throws IOException {
return new Object[][] {
{new LineNumberReader(new FileReader(file))},
{new CharArrayReader(new char[] {27})},
{new PushbackReader(new FileReader(file))},
{new FileReader(file)},
{new StringReader(new String(new byte[] {(byte)42}))}
};
}

@Test(dataProvider = "readers")
public void eof(Reader r) throws IOException {
r.skip(Long.MAX_VALUE);
Assert.assertEquals(r.skip(1), 0);
Assert.assertEquals(r.read(), -1);
}

@DataProvider(name = "skipIAE")
public Object[][] getSkipIAEs() throws IOException {
return new Object[][] {
{new LineNumberReader(new FileReader(file))},
{new PushbackReader(new FileReader(file))},
{new FileReader(file)}
};
}

@Test(dataProvider = "skipIAE", expectedExceptions = IllegalArgumentException.class)
public void testThrowsIAE(Reader r) throws IOException {
r.skip(-1);
}

@DataProvider(name = "skipNoIAE")
public Object[][] getSkipNoIAEs() throws IOException {
return new Object[][] {
{new CharArrayReader(new char[] {27})},
{new StringReader(new String(new byte[] {(byte)42}))}
};
}

@Test(dataProvider = "skipNoIAE")
public void testNoIAE(Reader r) throws IOException {
r.skip(-1);
}
}

1 comment on commit 7ffa148

@openjdk-notifier
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.