Почему hasNextLine () никогда не заканчивается?

Извините, если это звучит слишком просто. Я очень новичок в Java.

Вот простой код, который я использовал для проверки hasNextLine(). Когда я запускаю его, я не могу его остановить. Я подумал, что если вы не напишете ввод и нажмете Enter , вы избежите цикла while. /р>

Может ли кто-нибудь объяснить мне, как hasNextLine() работает в этой ситуации?

import java.util.*;

public class StringRaw {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNextLine()) {
            String str = sc.nextLine();
        }
        System.out.print("YOU'VE GOT THROUGH");
    }
}
12 голосов | спросил Helgi 13 PMpWed, 13 Apr 2011 21:44:44 +040044Wednesday 2011, 21:44:44

4 ответа


0

При чтении из System.in вы по умолчанию читаете с клавиатуры, и это бесконечный поток ввода ... в нем столько строк, сколько пользователь хочет набрать. Я думаю, что отправка управляющей последовательности для EOF может сработать, например, CTL-Z (или это CTL-D?).

Глядя на мою хорошую ASCII-диаграмму ... CTL-C - это ETX, а CTL-D - это EOT; любой из них должен работать, чтобы прекратить поток текста. CTL-Z - это SUB, который не должен работать (но это может произойти, поскольку элементы управления исторически интерпретируются очень субъективно).

ответил Lawrence Dol 13 PMpWed, 13 Apr 2011 21:46:11 +040046Wednesday 2011, 21:46:11
0

Нажмите Ctrl + D , чтобы завершить ввод со стандартного ввода. (Windows: Ctrl + Z ) или введите команду:

echo -e "abc\ndef" | java Program
ответил user unknown 13 PMpWed, 13 Apr 2011 21:47:04 +040047Wednesday 2011, 21:47:04
0

CTRL-D - это конец символьного или байтового потока для UNIX /Linux, а CTRL-Z - конец символьного или байтового потока для Windows (исторический артефакт с самых ранних дней Microsoft DOS).

При написанном коде вопроса пустая строка не выйдет из цикла, потому что hasNextLine () не будет иметь значение false. Он будет иметь ограничитель строки во входном байтовом потоке.

System.in - это поток байтов из стандартного ввода, обычно с консоли. Поэтому завершение потока байтов остановит цикл. Хотя nextLine () не блокирует ожидание ввода, hasNextLine () делает. Единственный способ, которым код завершается, как и было задумано, с помощью CTRL-Z в Windows или CTRL-D в UNIX /Linux, который завершает поток байтов, заставляет hasNextLine () не блокировать ожидание ввода и возвращать логическое значение false, которое завершается цикл while.

Если вы хотите, чтобы он заканчивался вводом пустой строки, вы можете проверить наличие непустых строк как часть условия продолжения цикла. Следующий код демонстрирует, как изменить базовый дизайн вопроса, который использует hasNextLine () и nextLine (), на тот, который заканчивается, если он получает пустую строку или конец вводимого символа (то есть CTRL-Z в Windows или CTRL-D в UNIX /Linux). Дополнительный код в условии while использует функцию операторов присваивания, в которой они могут оцениваться как выражение для возврата назначенного значения. Поскольку это объект String, метод String.equals () можно использовать с оценкой.

Другой дополнительный код просто добавляет вывод на печать, чтобы сделать происходящее очевидным.

// HasNextLineEndDemo.java
import java.util.*;

public class HasNextLineEndDemo {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // this code is a bit gee-whiz
        // the assignment expression gets assigned sc.nextLine()
        // only if there is one because of the &&
        // if hasNextLine() is false, everything after the &&
        // gets ignored
        // in addition, the assignment operator itself, if
        // executed, returns, just like a method return,
        // whatever was assigned to str which, 
        // as a String object, can be tested to see if it is empty
        // using the String.equals() method
        int i = 1; // input line counter
        String str = " "; // have to seed this to other than ""
        System.out.printf("Input line %d: ", i); // prompt user
        while (sc.hasNextLine() && !(str = sc.nextLine()).equals("")) {
            System.out.printf("Line %d: ", i);
            System.out.println("'" + str + "'");
            System.out.printf("Input line %d: ", ++i);
        } // end while
        System.out.println("\nYOU'VE GOT THROUGH");
    } // end main
} // end class HasNextLineEndDemo
ответил Jim 24 J000000Tuesday12 2012, 04:32:40
0

Насколько я понимаю, если вы возьмете пример объекта набора результатов из JDBC или любого итератора, то в этих случаях у вас будет конечный набор вещей, и итераторы каждый раз проверяют, достигнут ли конец набора. Однако в приведенном выше случае они не могут знать, что конец пользовательского ввода, то есть hasNextLine (), не могут узнать, когда пользователь хочет завершить работу, и, следовательно, он продолжается бесконечно. Лучший способ - поместить дополнительное условие в цикл for, который проверяет некоторое условие внутри цикла for, который завершится неудачей в будущем. В приведенном выше посте ответ @Jim иллюстрирует это.

На самом деле использование hasNextLine () в качестве ограничителя цикла для ввода с консоли не рекомендуется, поскольку оно никогда не вернет false.

ответил rootExplorr 30 52018vEurope/Moscow11bEurope/MoscowFri, 30 Nov 2018 04:10:23 +0300 2018, 04:10:23

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132