From 4285853d91e2d49e817975524a80bf46aad9e466 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 11 Sep 2019 12:32:01 -0700 Subject: [PATCH] 8230342: LineNumberReader.getLineNumber() returns inconsistent results after EOF Reviewed-by: rriggs, dfuchs --- .../share/classes/java/io/BufferedReader.java | 10 +++- .../classes/java/io/LineNumberReader.java | 6 +- test/jdk/java/io/LineNumberReader/Read.java | 59 ++++++++++++++++++- 3 files changed, 66 insertions(+), 9 deletions(-) diff --git a/src/java.base/share/classes/java/io/BufferedReader.java b/src/java.base/share/classes/java/io/BufferedReader.java index 8cb4f73e597..84e1a9e9462 100644 --- a/src/java.base/share/classes/java/io/BufferedReader.java +++ b/src/java.base/share/classes/java/io/BufferedReader.java @@ -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 @@ public class BufferedReader extends Reader { * (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 @@ public class BufferedReader extends Reader { * * @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 @@ public class BufferedReader extends Reader { 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 @@ public class BufferedReader extends Reader { * @see java.nio.file.Files#readAllLines */ public String readLine() throws IOException { - return readLine(false); + return readLine(false, null); } /** diff --git a/src/java.base/share/classes/java/io/LineNumberReader.java b/src/java.base/share/classes/java/io/LineNumberReader.java index bffda6e1c2c..1cfb90de2c9 100644 --- a/src/java.base/share/classes/java/io/LineNumberReader.java +++ b/src/java.base/share/classes/java/io/LineNumberReader.java @@ -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 class LineNumberReader extends BufferedReader { */ 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; } diff --git a/test/jdk/java/io/LineNumberReader/Read.java b/test/jdk/java/io/LineNumberReader/Read.java index 0e1968b372f..7f8b93db4e3 100644 --- a/test/jdk/java/io/LineNumberReader/Read.java +++ b/test/jdk/java/io/LineNumberReader/Read.java @@ -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 @@ public class Read { throw new Exception("Failed test: Expected line number: 2, got " + line); } + + private static void testEofs() throws Exception { + String string = "first \n second"; + + Consumer 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 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); + } }