Scanner.nextLine: примеры (JAVA)

Чтение строк в Java с помощью nextLine
Раздел: Сканирование ввода (Scanner)
Scanner.nextLine: String

Описание метода nextLine

Метод Scanner.nextLine() в Java возвращает оставшуюся часть текущей строки ввода как объект String, исключая символы-разделители строк. После вызова сканер продвигается за символы конца строки. Параметров у метода нет. Возвращаемое значение - строка с содержимым до ближайшего разделителя строки. Если входной поток завершён и строк для чтения нет, вызов nextLine() приводит к NoSuchElementException. Если экземпляр Scanner уже закрыт, будет выброшено IllegalStateException.

Поведение и особенности:

  • Метод читает до первой последовательности символов-разделителей строки. Разделители определяются внутренним регулярным выражением, эквивалентным \R, поэтому поддерживаются CR, LF и CRLF.
  • Возвращаемая строка не содержит символы разделителя строки.
  • Метод блокируется до тех пор, пока не встретит завершение строки или EOF.
  • nextLine() игнорирует текущий разделитель токенов (useDelimiter) и всегда ориентируется на границы строк.
  • Для проверки наличия следующей строки перед чтением применяется hasNextLine().
  • Кодировка ввода задаётся при создании сканера, например new Scanner(InputStream, "UTF-8"). При чтении из файлов можно использовать конструктор с Path и кодировкой.

Типичные исключения: NoSuchElementException - чтение после EOF; IllegalStateException - сканер закрыт.

Короткие примеры использования

Ниже примеры кода с результатами. В блоках кода класс для примера указан как pre class="ex_c", результат - pre class="ex_r".

1) Чтение одной строки из консоли:

import java.util.Scanner;

public class Example1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();
        System.out.println("Введено: " + line);
        scanner.close();
    }
}
Ввод:
Hello world
Результат:
Введено: Hello world

2) Чтение нескольких строк до пустой строки:

Scanner scanner = new Scanner(System.in);
while (scanner.hasNextLine()) {
    String s = scanner.nextLine();
    if (s.isEmpty()) break;
    System.out.println("Line: " + s);
}
scanner.close();
Ввод:
one
two

Результат:
Line: one
Line: two

3) Частая ошибка при комбинировании nextInt() и nextLine():

Scanner sc = new Scanner(System.in);
System.out.println("Введите число:");
int x = sc.nextInt();
System.out.println("Введите строку:");
String s = sc.nextLine(); // часто возвращает пустую строку
System.out.println("s='" + s + "'");
sc.close();
Ввод:
42
hello
Результат:
s=''
(пояснение: после nextInt() в буфере остался символ новой строки)

4) Исправление ошибки: дополнительный nextLine() или skip:

Scanner sc = new Scanner(System.in);
int x = sc.nextInt();
sc.nextLine(); // пропустить остаток строки
String s = sc.nextLine();
Ввод:
42
hello
Результат:
s='hello'

5) Чтение файла в UTF-8:

import java.nio.file.Paths;
import java.util.Scanner;

Scanner sc = new Scanner(Paths.get("file.txt"), "UTF-8");
while (sc.hasNextLine()) {
    System.out.println(sc.nextLine());
}
sc.close();
Результат: вывод строк файла без символов конца строки

Схожие методы в Java и их особенности

  • BufferedReader.readLine() - возвращает null при EOF, работает быстрее при большом объёме текста, удобно для построчного чтения из Reader.
  • Console.readLine() - удобен для интерактивного ввода в терминале, поддерживает чтение пароля через readPassword. Console может быть недоступен в средах без консоли (IDE).
  • Files.lines(Path) - возвращает поток строк Stream<String>, эффективен для обработки больших файлов с ленивыми операциями.
  • Scanner.next() - возвращает следующий токен по текущему разделителю (по умолчанию пробельный); полезен для разбора слов, но не читает пробелы внутри строки.

Выбор зависит от задачи: для простого построчного ввода подходит nextLine() или BufferedReader. Для потоковой обработки больших файлов предпочтительнее Files.lines. Для разбора токенов используется Scanner.next().

Типичные ошибки и примеры

  • Пустая строка после чтения числа: оставшийся символ новой строки после nextInt() делает первый nextLine() пустым. Пример: см. раздел примеров выше. Решения: вызвать дополнительный nextLine() или использовать skip("\\R").
  • Чтение после EOF приводит к NoSuchElementException:
Scanner sc = new Scanner("a\nb");
sc.nextLine(); // "a"
sc.nextLine(); // "b"
sc.nextLine(); // NoSuchElementException
Результат: выбрасывается java.util.NoSuchElementException на третьем вызове
  • Вызов после закрытия сканера вызывает IllegalStateException:
Scanner sc = new Scanner(System.in);
sc.close();
sc.nextLine(); // IllegalStateException
Результат: java.lang.IllegalStateException: Scanner closed
  • Проблемы с кодировкой при чтении из InputStream без указания кодировки; при использовании конструкторов с кодировкой рекомендуется явно указывать "UTF-8".
  • Ожидание ввода в средах без интерактивной консоли (IDE) может выглядеть как зависание программы.

Изменения и стабильность поведения

Класс Scanner и метод nextLine() введены в Java 5 (JDK 1.5) и с тех пор поведение метода остаётся стабильным. Документация уточняла распознавание разделителей строк через регулярное выражение, совместимое с \R, что обеспечивает корректную работу с CR, LF и CRLF во всех современных версиях JVM. В последних релизах изменений API самого метода не наблюдалось; улучшения в JVM и библиотеке касаются производительности и исправления мелких багов в реализации регулярных выражений.

Расширенные и редкие сценарии применения

1) Чтение строки из сокета (InputStream) построчно:

Пример java
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

try (ServerSocket ss = new ServerSocket(5555)) {
    Socket s = ss.accept();
    Scanner sc = new Scanner(s.getInputStream(), "UTF-8");
    while (sc.hasNextLine()) {
        String line = sc.nextLine();
        // обработка
    }
    sc.close();
}
Результат: получение текстовых линий от клиента; важно закрывать ресурсы и учитывать блокировки

2) Использование skip для аккуратного пропуска символа новой строки:

Пример java
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
try { sc.skip("\\R"); } catch (java.util.NoSuchElementException e) { /* нет разделителя */ }
String rest = sc.nextLine();
Пояснение: skip("\\R") удаляет один разделитель строки, если он там есть, избегая пустой строки от nextLine()

3) Чтение блока до специального маркера (например, "END"):

Пример java
Scanner sc = new Scanner(System.in);
StringBuilder sb = new StringBuilder();
while (sc.hasNextLine()) {
    String line = sc.nextLine();
    if ("END".equals(line)) break;
    sb.append(line).append(System.lineSeparator());
}
System.out.println("Получено:\n" + sb.toString());
sc.close();
Ввод:
first
second
END
Результат:
Получено:
first
second

4) Парсинг многострочного блока в объекты с помощью регулярных шаблонов:

Пример java
String input = "name:John\nage:30\ncity:NY\n";
Scanner sc = new Scanner(input);
while (sc.hasNextLine()) {
    String line = sc.nextLine();
    String[] parts = line.split(":", 2);
    if (parts.length == 2) {
        System.out.printf("key=%s val=%s%n", parts[0], parts[1]);
    }
}
sc.close();
Результат:
key=name val=John
key=age val=30
key=city val=NY

5) Быстрое подсчитывание строк в большом файле (альтернатива nextLine - Files.lines):

Пример java
long count = 0;
try (Scanner sc = new Scanner(Paths.get("big.txt"), "UTF-8")) {
    while (sc.hasNextLine()) { sc.nextLine(); count++; }
}
System.out.println(count);
Результат: количество строк; для очень больших файлов чаще предпочтительнее Streams API и параллельная обработка

Аналоги в других языках и отличия

  • Python: input() или sys.stdin.readline(). input() возвращает строку без символа конца строки; блокирует до ввода. Пример:
    s = input()
    print('s="' + s + '"')
    Ввод:
    Hello
    Результат:
    s="Hello"
  • JavaScript (Node.js): модуль readline. Пример:
    const rl = require('readline').createInterface({ input: process.stdin, output: process.stdout });
    rl.on('line', (line) => { console.log('s="' + line + '"'); rl.close(); });
    Ввод:
    Hello
    Результат:
    s="Hello"
  • PHP: fgets(STDIN) возвращает строку с символом конца строки; часто применяется rtrim() для удаления. Пример:
    $s = fgets(STDIN);
    $s = rtrim($s, "\r\n");
    echo "s=\"$s\"\n";
    Ввод:
    Hello
    Результат:
    s="Hello"
  • C#: Console.ReadLine() возвращает строку без символа конца строки или null на EOF.
    string s = Console.ReadLine();
    Console.WriteLine($"s=\"{s}\"");
    Ввод:
    Hello
    Результат:
    s="Hello"
  • Go: bufio.NewReader(os.Stdin).ReadString('\n') возвращает строку, включая разделитель; для удаления используется strings.TrimSuffix.
    r := bufio.NewReader(os.Stdin)
    s, _ := r.ReadString('\n')
    s = strings.TrimRight(s, "\r\n")
    fmt.Println("s=\"" + s + "\"")
    Ввод:
    Hello
    Результат:
    s="Hello"
  • Kotlin: readLine() возвращает строку без символа конца строки или null при EOF. Поведение близко к Python и C#.
  • Lua: io.read() читает строку без конца строки по умолчанию.
  • SQL: понятие построчного чтения не применяется в языке запросов. Чтение входа выполняется средствами клиентской библиотеки.

Отличия от Java: в большинстве языков возвращается null или строка без разделителя, но механика блокировки, обработка EOF и доступность консоли могут отличаться. В Java при отсутствии строки бросается исключение, поэтому перед вызовом удобно использовать hasNextLine().

джава Scanner.nextLine function comments

En
Scanner.nextLine Advances this scanner past the current line and returns the input that was skipped