--- old/src/java.base/share/classes/java/io/LineNumberReader.java 2020-03-13 08:22:52.000000000 -0700 +++ new/src/java.base/share/classes/java/io/LineNumberReader.java 2020-03-13 08:22:51.000000000 -0700 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2020, 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 @@ -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 @@ -33,10 +32,11 @@ * respectively. * *

By default, line numbering begins at 0. This number increments at every - * line terminator as the data is read, and can be changed - * with a call to {@code setLineNumber(int)}. Note however, that - * {@code setLineNumber(int)} does not actually change the current position in - * the stream; it only changes the value that will be returned by + * line terminator as the data is read, and at the end of the + * stream if the last character in the stream is not a line terminator. This + * number can be changed with a call to {@code setLineNumber(int)}. Note + * however, that {@code setLineNumber(int)} does not actually change the current + * position in the stream; it only changes the value that will be returned by * {@code getLineNumber()}. * *

A line is considered to be terminated by any one of a @@ -49,6 +49,15 @@ public class LineNumberReader extends BufferedReader { + /** Previous character types */ + private static final int NONE = 0; // no previous character + private static final int CHAR = 1; // non-line terminator + private static final int EOL = 2; // line terminator + private static final int EOF = 3; // end-of-file + + /** The previous character type */ + private int prevChar = NONE; + /** The current line number */ private int lineNumber = 0; @@ -111,8 +120,10 @@ /** * Read a single character. Line terminators are - * compressed into single newline ('\n') characters. Whenever a line - * terminator is read the current line number is incremented. + * compressed into single newline ('\n') characters. The current line + * number is incremented whenever a line terminator is read, or when the + * end of the stream is reached and the last character in the stream is + * not a line terminator. * * @return The character read, or -1 if the end of the stream has been * reached @@ -134,16 +145,26 @@ skipLF = true; case '\n': /* Fall through */ lineNumber++; + prevChar = EOL; return '\n'; + case -1: + if (prevChar == CHAR) + lineNumber++; + prevChar = EOF; + break; + default: + prevChar = CHAR; + break; } return c; } } /** - * Read characters into a portion of an array. Whenever a line terminator is read the current line number is - * incremented. + * Read characters into a portion of an array. The current line + * number is incremented whenever a line terminator is read, or when the + * end of the stream is reached and the last character in the stream is + * not a line terminator. * * @param cbuf * Destination buffer @@ -167,6 +188,13 @@ synchronized (lock) { int n = super.read(cbuf, off, len); + if (n == -1) { + if (prevChar == CHAR) + lineNumber++; + prevChar = EOF; + return -1; + } + for (int i = off; i < off + n; i++) { int c = cbuf[i]; if (skipLF) { @@ -183,13 +211,26 @@ } } + if (n > 0) { + switch ((int)cbuf[off + n - 1]) { + case '\r': + case '\n': /* Fall through */ + prevChar = EOL; + break; + default: + prevChar = CHAR; + break; + } + } + return n; } } /** - * Read a line of text. Whenever a line terminator is - * read the current line number is incremented. + * Read a line of text. The current line number is incremented whenever + * a line terminator is read, or when the end of the stream is reached and + * the last character in the stream is not a line terminator. * * @return A String containing the contents of the line, not including * any line termination characters, or @@ -200,10 +241,17 @@ */ 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) { lineNumber++; + prevChar = term[0] ? EOL : EOF; + } else { // l == null + if (prevChar == CHAR) + lineNumber++; + prevChar = EOF; + } return l; } } @@ -242,6 +290,9 @@ break; r -= nc; } + if (n - r > 0) { + prevChar = NONE; + } return n - r; } }