W3docs

Пользовательский ввод в Java с Scanner

Чтение ввода с консоли в Java через класс Scanner — nextInt, nextDouble, nextLine и валидация ввода.

Для большинства начинающих программистов самый простой способ читать ввод с клавиатуры — это java.util.Scanner. Он оборачивает System.in (стандартный поток ввода) и предоставляет методы nextInt, nextDouble и nextLine. В этой главе рассматриваются API Scanner, известная проблема «Scanner пропускает строку» и альтернативы, когда Scanner перестаёт подходить.

Создание Scanner

Scanner находится в пакете java.util, поэтому нужен import:

import java.util.Scanner;

public class Greeter {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        System.out.print("What is your name? ");
        String name = in.nextLine();
        System.out.println("Hello, " + name + "!");
    }
}

Scanner следует закрывать после использования — но если закрыть scanner над System.in, стандартный ввод будет закрыт для всей программы. В коротких скриптах можно пропустить close(). В более длинном коде используйте try-with-resources для scanner'ов над файлами, но не для System.in.

Методы чтения

МетодЧитает
nextLine()остаток текущей строки (без \n)
next()следующий токен, разделённый пробелами
nextInt()следующий токен, разобранный как int
nextLong()…как long
nextDouble()…как double
nextBoolean()…как boolean
hasNext()true, если доступен ещё один токен
hasNextInt()true, если следующий токен является корректным int
hasNextLine()true, если доступна ещё одна строка

Используйте варианты hasNext... для проверки ввода перед его считыванием.

Полный цикл запросов

import java.util.Scanner;

public class Calculator {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);

        System.out.print("First number: ");
        double a = in.nextDouble();

        System.out.print("Second number: ");
        double b = in.nextDouble();

        System.out.println("Sum: " + (a + b));
    }
}

Если пользователь вводит не число, nextDouble бросает InputMismatchException. Обработку этого мы рассмотрим ниже.

Классическая проблема — nextInt оставляет символ новой строки

После nextInt() или nextDouble() scanner оставляет завершающий символ новой строки в буфере. Следующий вызов nextLine() вернёт пустую строку:

System.out.print("age? ");
int age = in.nextInt();        // user types "30" then Enter

System.out.print("name? ");
String name = in.nextLine();   // returns "" — the leftover newline
String name2 = in.nextLine();  // returns the typed name

Два распространённых способа исправить это:

  • После nextInt() / nextDouble() вызывайте in.nextLine(), чтобы сбросить остаток строки.
  • Используйте nextLine() везде и разбирайте строку самостоятельно:
System.out.print("age? ");
int age = Integer.parseInt(in.nextLine().trim());

Второй стиль становится чище, когда нужна валидация.

Валидация с hasNext...

Scanner in = new Scanner(System.in);
System.out.print("Enter a number: ");

while (!in.hasNextInt()) {
    System.out.print("That isn't an integer. Try again: ");
    in.next();   // discard the bad token
}
int value = in.nextInt();
System.out.println("You entered: " + value);

Чтение до конца файла

Распространённый шаблон пакетной обработки — читать, пока пользователь не нажмёт Ctrl+D (Linux/macOS) или Ctrl+Z затем Enter (Windows):

Scanner in = new Scanner(System.in);
int total = 0;
while (in.hasNextInt()) {
    total += in.nextInt();
}
System.out.println("Total: " + total);

BufferedReader — когда Scanner недостаточно быстр

Для соревновательного программирования или при чтении десятков тысяч строк BufferedReader значительно быстрее Scanner:

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

BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String line = br.readLine();
int n = Integer.parseInt(line.trim());

Кода чуть больше, но ускорение в 10–20 раз — обычное дело.

System.console() — только для интерактивных сессий

Когда программа подключена к реальному терминалу, System.console() возвращает объект Console с readLine и readPassword (который не отображает символы):

java.io.Console c = System.console();
if (c != null) {
    String user = c.readLine("Username: ");
    char[] pass = c.readPassword("Password: ");
    // ... use pass ...
    java.util.Arrays.fill(pass, ' ');  // zero out the password buffer
}

System.console() возвращает null, когда программа запускается через IDE, перенаправляющую stdin, поэтому не полагайтесь на него для общего ввода.

Демонстрация

Приведённый ниже запускаемый код использует System.in. Поскольку runner не поддерживает интерактивный ввод, в этой версии чтение идёт из фиксированной строки — что близко к обычному использованию Scanner:

java— editable, runs on the server

Что дальше

Часть 2 на этом завершается. Следующая часть, Управление потоком, начинается с Java if, else и else if и продолжается switch и циклами, которые лежат в основе большинства программной логики.

Практика

Практика
После вызова scanner.nextInt(), почему следующий scanner.nextLine() часто возвращает пустую строку?
После вызова scanner.nextInt(), почему следующий scanner.nextLine() часто возвращает пустую строку?
Was this page helpful?