Почему Java просит меня снова нажать Enter?

Я некоторое время ломал голову, пытаясь понять, как работает сканер. Итак, вот код:

Scanner sc = new Scanner(System.in);
String s = sc.nextLine();
String p = sc.nextLine();
System.out.println(s);
System.out.println(p);
System.out.println(sc.hasNextLine());

Что Я ожидал:

Love is good  <- press ENTER
Love is blind <- press ENTER
Love is good  <- output
Love is blind <- output
false

Что Я есть:

Love is good   <- I press ENTER
Love is blind  <- I press ENTER
Love is good   <- output
Love is blind  <- output
<- press ENTER
true <- output

Что Я не понимаю:

  1. вместо немедленной печати этой линейной системы.из.println(sc.hasNextLine ()); - это заставляет меня снова нажать ENTER
  2. он печатает true вместо false, пока там нет больше линий или символов

Что Я читать: Я есть прочитайте дюжину ответов stackoverflow об использовании hasNextLine () после nextInt() и о том, как nextInt() не использует конечный символ в строке, но я не понимаю, почему, хотя я не использую nextInt() здесь, мне все равно нужно нажать ENTER еще раз и почему hasnextline () истинно.

6 ответов


вместо Scanner использовать BufferedReader вот так:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

class Test {
    public static void main(String[] args) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

        String s = reader.readLine();
        String p = reader.readLine();
        System.out.println(s);
        System.out.println(p);      
        System.out.println(reader.ready());
    }
}

для большего чтения в этом вопросе, посмотрите здесь и здесь. Как правило, когда вам нужен разбор материала (например,nextInt) использовать Scanner, в противном случае придерживайтесь BufferedReader. BufferedReader намного быстрее, чем Scanner тоже.

что касается того, почему вы получили это хлопотное поведение, см. javadoc на Scanner.

часть, которая применяется в вашем конкретном случае:

операция сканирования может блокировать ожидание ввода.

что это означает в вашем случае: после того, как первые две строки читаются Scanner на Scanner ждал ввода, вызванного его вызовом метода sc.hasNextLine(). Тогда когда Enter был поражен, он получил вход (следовательно, он печатает true, по данным docs возвращает true когда есть вход). Как после вызова метода sc.hasNextLine() в вашей программе больше нет исполняемых строк, программа заканчивается, создавая иллюзию, что она требуется два введите хиты.


С сканер документация (выделено мной):

public boolean hasNextLine()

возвращает true, если на входе этого сканера есть другая строка. этот метод может блокировать во время ожидания ввода. Сканер не проходит мимо входа.

что, вероятно, происходит вот что:hasNextLine блокируется, потому что он ждет ввода, который вы даете, нажав enter.


прежде всего вы используете сканер, объявленный системе.таким образом, это означает, что вы просите .в, чтобы проверить, если их больше значение, поэтому он ждет пользователя, чтобы ввести что-то, и после нажатия enter очевидно, что он возвращает true.

поэтому, если вы хотите проверить S или P, объявите сканер следующим образом:

Scanner sc = new Scanner(s);

или

Scanner sc = new Scanner(p);

тогда проверьте на sc.hasNextLine(); это должно вернуть false, как я знаю, но для ввода пользователя я бы рекомендовал создать другой Переменная сканера, а затем принимать значения от пользователя и использовать sc для вашего hasNextline() вещь.

Я надеюсь, что первая логика поможет вам.


вы прошу в течение трех строк!

стандартный ввод всегда есть еще одна строка, пока вы закрыть терминал. В системе Unix вы, вероятно, можете нажать Ctrl+D в конце, и он вернет flase (= вход закрыт).

программа будет вести себя так, как ожидалось, если у вас есть конечная вход. Но интерактивный ввод:как программа знает, что пользователь не намерен ввод Шекспира далее?

функции hasNextLine() будет дождитесь нового ввода (или для сигнала, что не может быть нового входа). Эта функция не для "сделал уже введите другую строку "но вместо этого означает"ждать на следующей строке". Так что для практических целей,hasNextLine() эквивалентно "является ли пользовательский ввод все еще подключен, и мог бы в конечном итоге он содержит другую строку".

почему вы нужна последняя строчка? Просто удалить это!


у вас есть проблема, что сканер читает из указанного InputStream который может быть чем-то вроде файла или в вашем случае система.в.

как описано в этой ответ файл имеет конец и sc.hasNextLine() возвращает false. Используя поток, вы ожидаете, что он не будет иметь конца, чтобы иметь возможность предоставлять входные данные, и поэтому будет блокировать и ждать следующего ввода.

возможно, вы можете подумать какой-то" выходящий символ " (вот он '#'):

Scanner sc = new Scanner(System.in);
StringBuilder builder = new StringBuilder();
while (sc.hasNextLine()) {
    String line = sc.nextLine();
    if (line.equals("#")) {
        break;
    }
    builder.append(line + "\n");
}
System.out.println(builder.toString());
sc.close();

в вашем случае, я отладил свой пример и увидел, что

System.out.println(sc.hasNextLine());

строка ожидает нового ввода. Она ни истинна, ни ложна. Его не существует. Именно поэтому, он блокирует приложение. Не имеет значения, что вы ввели (enter или любую другую кнопку на клавиатуре), это даст вам true, потому что вы предоставили новый ввод.