Scanner.nextLine: примеры (JAVA)
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().
Аналоги в других языках и отличия
- 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().
Типичные ошибки и примеры
- Пустая строка после чтения числа: оставшийся символ новой строки после
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) построчно:
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 для аккуратного пропуска символа новой строки:
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"):
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) Парсинг многострочного блока в объекты с помощью регулярных шаблонов:
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):
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 и параллельная обработка