Подтвердить что ты не робот

Почему 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
4b9b3361

Ответ 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 1hasNextLine()? Правда. hasNext()? Также верно.

1 1hasNextLine()? Правда. hasNext()? Также верно (все еще осталось пробел)

1hasNextLine()? True (Линейный разделитель, возможно). haxNext? False, без пробелов.