8230342: LineNumberReader.getLineNumber() returns inconsistent results after EOF
Reviewed-by: rriggs, dfuchs
--- a/src/java.base/share/classes/java/io/BufferedReader.java Wed Sep 11 11:55:31 2019 -0700
+++ b/src/java.base/share/classes/java/io/BufferedReader.java Wed Sep 11 12:32:01 2019 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1996, 2017, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2019, 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
@@ -302,6 +302,8 @@
* (EOF).
*
* @param ignoreLF If true, the next '\n' will be skipped
+ * @param term Output: Whether a line terminator was encountered
+ * while reading the line; may be {@code null}.
*
* @return A String containing the contents of the line, not including
* any line-termination characters, or null if the end of the
@@ -311,13 +313,14 @@
*
* @exception IOException If an I/O error occurs
*/
- String readLine(boolean ignoreLF) throws IOException {
+ String readLine(boolean ignoreLF, boolean[] term) throws IOException {
StringBuffer s = null;
int startChar;
synchronized (lock) {
ensureOpen();
boolean omitLF = ignoreLF || skipLF;
+ if (term != null) term[0] = false;
bufferLoop:
for (;;) {
@@ -344,6 +347,7 @@
for (i = nextChar; i < nChars; i++) {
c = cb[i];
if ((c == '\n') || (c == '\r')) {
+ if (term != null) term[0] = true;
eol = true;
break charLoop;
}
@@ -389,7 +393,7 @@
* @see java.nio.file.Files#readAllLines
*/
public String readLine() throws IOException {
- return readLine(false);
+ return readLine(false, null);
}
/**
--- a/src/java.base/share/classes/java/io/LineNumberReader.java Wed Sep 11 11:55:31 2019 -0700
+++ b/src/java.base/share/classes/java/io/LineNumberReader.java Wed Sep 11 12:32:01 2019 -0700
@@ -25,7 +25,6 @@
package java.io;
-
/**
* A buffered character-input stream that keeps track of line numbers. This
* class defines methods {@link #setLineNumber(int)} and {@link
@@ -200,9 +199,10 @@
*/
public String readLine() throws IOException {
synchronized (lock) {
- String l = super.readLine(skipLF);
+ boolean[] term = new boolean[1];
+ String l = super.readLine(skipLF, term);
skipLF = false;
- if (l != null)
+ if (l != null && term[0])
lineNumber++;
return l;
}
--- a/test/jdk/java/io/LineNumberReader/Read.java Wed Sep 11 11:55:31 2019 -0700
+++ b/test/jdk/java/io/LineNumberReader/Read.java Wed Sep 11 12:32:01 2019 -0700
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2019, 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
@@ -22,16 +22,24 @@
*/
/* @test
- @bug 4074875 4063511
+ @bug 4074875 4063511 8230342
@summary Make sure LineNumberReader.read(char, int , int) will increase
the linenumber correctly.
*/
-import java.io.*;
+import java.io.IOException;
+import java.io.LineNumberReader;
+import java.io.StringReader;
+import java.util.function.Consumer;
public class Read {
public static void main(String[] args) throws Exception {
+ testReadChars();
+ testEofs();
+ }
+
+ private static void testReadChars() throws Exception {
String s = "aaaa\nbbb\n";
char[] buf = new char[5];
int n = 0;
@@ -49,4 +57,49 @@
throw new Exception("Failed test: Expected line number: 2, got "
+ line);
}
+
+ private static void testEofs() throws Exception {
+ String string = "first \n second";
+
+ Consumer<LineNumberReader> c = (LineNumberReader r) -> {
+ try {
+ while (r.read() != -1)
+ continue;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ testEof(c, string, 1);
+
+ c = (LineNumberReader r) -> {
+ try {
+ char[] buf = new char[128];
+ while (r.read(buf) != -1)
+ continue;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ testEof(c, string, 1);
+
+ c = (LineNumberReader r) -> {
+ try {
+ while (r.readLine() != null)
+ continue;
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ };
+ testEof(c, string, 1);
+ }
+
+ private static void testEof(Consumer<LineNumberReader> c, String s, int n)
+ throws Exception {
+ LineNumberReader r = new LineNumberReader(new StringReader(s));
+ c.accept(r);
+ int line;
+ if ((line = r.getLineNumber()) != n)
+ throw new Exception("Failed test: Expected line number: " + n +
+ " , got " + line);
+ }
}