< prev index next >
src/java.base/share/classes/java/io/LineNumberReader.java
Print this page
*** 1,7 ****
/*
! * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
--- 1,7 ----
/*
! * 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
*** 23,56 ****
* questions.
*/
package java.io;
-
/**
* A buffered character-input stream that keeps track of line numbers. This
* class defines methods {@link #setLineNumber(int)} and {@link
* #getLineNumber()} for setting and getting the current line number
* respectively.
*
* <p> By default, line numbering begins at 0. This number increments at every
! * <a href="#lt">line terminator</a> 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
* {@code getLineNumber()}.
*
* <p> A line is considered to be <a id="lt">terminated</a> by any one of a
* line feed ('\n'), a carriage return ('\r'), or a carriage return followed
! * immediately by a linefeed.
*
* @author Mark Reinhold
* @since 1.1
*/
public class LineNumberReader extends BufferedReader {
/** The current line number */
private int lineNumber = 0;
/** The line number of the mark, if any */
private int markedLineNumber; // Defaults to 0
--- 23,66 ----
* questions.
*/
package java.io;
/**
* A buffered character-input stream that keeps track of line numbers. This
* class defines methods {@link #setLineNumber(int)} and {@link
* #getLineNumber()} for setting and getting the current line number
* respectively.
*
* <p> By default, line numbering begins at 0. This number increments at every
! * <a href="#lt">line terminator</a> 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()}.
*
* <p> A line is considered to be <a id="lt">terminated</a> by any one of a
* line feed ('\n'), a carriage return ('\r'), or a carriage return followed
! * immediately by a linefeed, or any of the previous terminators followed by
! * end of stream, or end of stream not preceded by another terminator.
*
* @author Mark Reinhold
* @since 1.1
*/
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;
/** The line number of the mark, if any */
private int markedLineNumber; // Defaults to 0
*** 109,120 ****
return lineNumber;
}
/**
* Read a single character. <a href="#lt">Line terminators</a> are
! * compressed into single newline ('\n') characters. Whenever a line
! * terminator is read the current line number is incremented.
*
* @return The character read, or -1 if the end of the stream has been
* reached
*
* @throws IOException
--- 119,132 ----
return lineNumber;
}
/**
* Read a single character. <a href="#lt">Line terminators</a> are
! * 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
*
* @throws IOException
*** 132,151 ****
switch (c) {
case '\r':
skipLF = true;
case '\n': /* Fall through */
lineNumber++;
return '\n';
}
return c;
}
}
/**
! * Read characters into a portion of an array. Whenever a <a
! * href="#lt">line terminator</a> is read the current line number is
! * incremented.
*
* @param cbuf
* Destination buffer
*
* @param off
--- 144,173 ----
switch (c) {
case '\r':
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. 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
*
* @param off
*** 165,174 ****
--- 187,203 ----
@SuppressWarnings("fallthrough")
public int read(char cbuf[], int off, int len) throws IOException {
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) {
skipLF = false;
if (c == '\n')
*** 181,211 ****
lineNumber++;
break;
}
}
return n;
}
}
/**
! * Read a line of text. Whenever a <a href="#lt">line terminator</a> is
! * read the current line number is incremented.
*
* @return A String containing the contents of the line, not including
* any <a href="#lt">line termination characters</a>, or
* {@code null} if the end of the stream has been reached
*
* @throws IOException
* If an I/O error occurs
*/
public String readLine() throws IOException {
synchronized (lock) {
! String l = super.readLine(skipLF);
skipLF = false;
! if (l != null)
lineNumber++;
return l;
}
}
/** Maximum skip-buffer size */
--- 210,260 ----
lineNumber++;
break;
}
}
+ 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. 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 <a href="#lt">line termination characters</a>, or
* {@code null} if the end of the stream has been reached
*
* @throws IOException
* If an I/O error occurs
*/
public String readLine() throws IOException {
synchronized (lock) {
! boolean[] term = new boolean[1];
! String l = super.readLine(skipLF, term);
skipLF = false;
! if (l != null) {
! lineNumber++;
! prevChar = term[0] ? EOL : EOF;
! } else { // l == null
! if (prevChar == CHAR)
lineNumber++;
+ prevChar = EOF;
+ }
return l;
}
}
/** Maximum skip-buffer size */
*** 240,249 ****
--- 289,301 ----
int nc = read(skipBuffer, 0, (int) Math.min(r, nn));
if (nc == -1)
break;
r -= nc;
}
+ if (n - r > 0) {
+ prevChar = NONE;
+ }
return n - r;
}
}
/**
< prev index next >