Почему hasNext() False, но hasNextLine() True?
Вопрос
Как это выглядит для объекта сканера, метод hasNextLine()
возвращает true, а метод hasNext()
возвращает false?
Примечание. На основе входного файла метод hasNext()
возвращает результат, как ожидалось; hasNextLine()
, похоже, не возвращает правильный результат.
код
Вот код, который я запускаю, создавая следующие результаты:
public void ScannerTest(Reader fileReaderObject){
Scanner scannerObj = new Scanner(fileReaderObject);
for(int i = 1; scannerObj.hasNext(); i++){
System.out.println(i + ": " + scannerObj.next());
System.out.println("Has next line: " + scannerObj.hasNextLine());
System.out.println("Has next: " + scannerObj.hasNext());
}
System.out.println();
scannerObj.close();
}
Входной файл
Ниже приведен фактический контент файла, который я передаю этому сканеру:
a 3 9
b 3 6
c 3 3
d 2 8
e 2 5
f 2 2
g 1 7
h 1 4
i 1 1
Результат
Ниже приведен конец того, что напечатано на консоли при запуске моего кода, и включает в себя часть, о которой я не могу понять:
25: i
Has next line: true
Has next: true
26: 1
Has next line: true
Has next: true
27: 1
Has next line: true
Has next: false
Ответы
Ответ 1
У вас есть еще одна новая строка в конце вашего файла.
-
hasNextLine()
проверяет, есть ли в буфере другой linePattern
.
-
hasNext()
проверяет, существует ли в буфере синтаксический анализатор, разделенный разделителем сканера.
Так как разделитель сканера представляет собой пробел, а linePattern
также является пробелом, возможно, что в буфере есть linePattern
, но не токены синтаксического анализа.
Как правило, наиболее распространенный способ справиться с этой проблемой, всегда вызывая nextLine()
после разбора всех токенов (например, цифр) в каждой строке вашего текста. Это необходимо сделать при использовании Scanner
при чтении ввода пользователя также с System.in
. Чтобы продвинуть сканер мимо этого разделителя пробелов, вы должны использовать scanner.nextLine()
, чтобы очистить разделитель строк. Смотрите: Использование scanner.nextLine()
Приложение:
linePattern
определяется как Pattern
, который соответствует этому:
private static final String LINE_SEPARATOR_PATTERN =
"\r\n|[\n\r\u2028\u2029\u0085]";
private static final String LINE_PATTERN = ".*("+LINE_SEPARATOR_PATTERN+")|.+$";
Разделитель маркеров по умолчанию - это Pattern
:
private static Pattern WHITESPACE_PATTERN = Pattern.compile(
"\\p{javaWhitespace}+");
Ответ 2
Причина в том, что hasNext()
проверяет, имеются ли еще не-пробельные символы. hasNextLine()
проверяет, есть ли другая строка текста. У вашего текстового файла, вероятно, есть новая строка в конце, поэтому у него есть другая строка, но не больше символов, которые не являются пробелами.
Многие текстовые редакторы автоматически добавляют новую строку в конец файла, если он еще не существует.
Другими словами, ваш входной файл не является этим (цифры являются номерами строк):
1. a 3 9
2. b 3 6
3. c 3 3
4. d 2 8
5. e 2 5
На самом деле это:
1. a 3 9
2. b 3 6
3. c 3 3
4. d 2 8
5. e 2 5
6.
Ответ 3
Короткий ответ
У вас есть пустая строка в конце файла.
Причина пустой строки
Если вы возьмете свой контент и сохраните его, например, в txt файл, некоторые редакторы добавят пустую новую строку в ваш файл.
Редакторы ведут себя таким образом, потому что это часть стандарта POSIX:
3.206 Линия
Последовательность из нуля или более несимволов плюс конечный символ.
Этот раздел обсуждался в этой теме.
Документация Java-сканера
Вот документация из класс Java 8 Scanner.
hasNext()
Возвращает true, если этот сканер имеет другой токен на своем входе.
hasNextLine()
Возвращает true, если на входе этого сканера есть еще одна строка.
Причина поведения кода Java
Из-за вышеописанных фактов hasNextLine()
вернет true
, но hasNext()
не сможет найти что-либо, что он может распознать как Token
и поэтому возвращает false
.
За дополнительной информацией см. durron597.
Ответ 4
Вы потребляете значение next()
, но запрашиваете hasNext()
и hasNextLine()
. next()
, по умолчанию, возвращает все к следующему whitespace()
. Таким образом, вы выполняете итерацию через все пробельные разделенные строки, и после каждого из них вы спрашиваете о nextLine()
.
i 1 1
→ hasNextLine()
? Правда. hasNext()
? Также верно.
1 1
→ hasNextLine()
? Правда. hasNext()
? Также верно (все еще осталось пробел)
1
→ hasNextLine()
? True (Линейный разделитель, возможно). haxNext? False, без пробелов.