Поиск по сайту:

Класс сканера в Java


Класс Java Scanner является частью пакета java.util. Он был представлен в версии Java 1.5. Сканер в основном используется для получения пользовательского ввода и анализа их в примитивные типы данных, такие как int, double или String по умолчанию. Это служебный класс для анализа данных с использованием регулярных выражений путем создания токенов.

Конструкторы класса сканера Java

Если вы посмотрите на класс Scanner, то увидите множество конструкторов.

Большинство конструкторов используют один из трех объектов:

  1. InputStream — наиболее распространенный способ передачи System.in для получения пользовательского ввода.
  2. Файл или путь. Мы также можем сканировать данные файла и работать со значениями из файла.
  3. Строка. Мы также можем создать сканер для строкового источника и анализировать из него значения.

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

Важные методы класса Scanner

Давайте рассмотрим некоторые из наиболее часто используемых методов класса Scanner.

  • useDelimiter(String pattern) — разделитель, который будет использоваться для сканера. Разделителем по умолчанию является пробел.
  • hasNext() — возвращает true, если во входных данных есть другой токен. Это метод блокировки, и он будет ожидать ввода данных пользователем.
  • next() — возвращает следующий токен из сканера. Он используется в сочетании с методом hasNext().
  • close() — для сканера требуется много ресурсов, поэтому после завершения работы используйте этот метод, чтобы закрыть его и освободить системные ресурсы.

Существует множество служебных методов для проверки и прямого анализа входного токена в int, short, long, byte, BigDecimal и т. д.

Шаги по инициализации и использованию сканера

  1. Первый шаг — инициализировать класс сканера с помощью соответствующего конструктора на основе типа ввода, например InputStream, File или String. При необходимости задайте используемый разделитель и набор символов.
  2. Второй шаг — ожидание входного токена с помощью метода hasNext().
  3. Затем используйте метод next(), чтобы прочитать токен и обработать их один за другим.

Как работает сканер?

  • Класс Scanner разбивает входные данные на токены, используя указанный шаблон разделителя.
  • Методы next() используются для чтения токенов по одному и их обработки.
  • Наконец, закройте экземпляр сканера, чтобы освободить системные ресурсы.

Примеры сканеров

Давайте рассмотрим некоторые распространенные варианты использования класса Scanner с примерами фрагментов кода.

1. Чтение пользовательского ввода

Это наиболее распространенное использование класса Scanner. Мы можем создать экземпляр с System.in в качестве источника ввода и прочитать пользовательский ввод.

// read user input
Scanner sc = new Scanner(System.in);
System.out.println("Please enter your name");
String name = sc.next();
System.out.println("Hello " + name);
sc.close();

Выход:

Please enter your name
Pankaj
Hello Pankaj

Ну, это выглядит легко и работает нормально. Но в приведенном выше коде есть проблема. Не читая следующий раздел, можете ли вы проверить код и попытаться идентифицировать его?

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

Please enter your name
Pankaj Kumar
Hello Pankaj

Теперь вы, должно быть, поняли, это происходит потому, что разделителем является пробел. Сканер разбивает ввод на два токена — Pankaj и Kumar. Но мы вызываем метод next() только один раз, поэтому печатается только \Hello Pankaj.

Как это исправить?

Это просто. Мы можем изменить разделитель на символ новой строки, используя метод useDelimiter().

Scanner sc = new Scanner(System.in);
sc.useDelimiter(System.getProperty("line.separator"));
System.out.println("Please enter your name");
String name = sc.next();
System.out.println("Hello " + name);
sc.close();

2. Разбор данных файла с помощью сканера

Давайте рассмотрим простой пример чтения и анализа CSV-файлов с использованием класса сканера. Допустим, у меня есть файл employee.csv со следующим содержимым.

1,Jane Doe,CEO
2,Mary Ann,CTO
3,John Lee,CFO

Давайте прочитаем файл и получим список сотрудников в нашей Java-программе.

package com.journaldev.java;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class ScannerExamples {

	public static void main(String[] args) throws IOException {

		// create scanner for the CSV file
		Scanner sc = new Scanner(new File("employees.csv"));

		// set delimiter as new line to read one line as a single token
		sc.useDelimiter(System.getProperty("line.separator"));

		// create the List of Employees
		List<Employee> emps = new ArrayList<>();

		while (sc.hasNext()) {
			Employee emp = parseEmployeeData(sc.next());
			emps.add(emp);
		}

		// close the scanner
		sc.close();

		// print employee records
		System.out.println(emps);
	}

	private static Employee parseEmployeeData(String record) {
		// create scanner for the String record
		Scanner sc = new Scanner(record);

		// set delimiter as comma
		sc.useDelimiter(",");

		Employee emp = new Employee();
		emp.setId(sc.nextInt());
		emp.setName(sc.next());
		emp.setRole(sc.next());

		// close the scanner
		sc.close();

		return emp;
	}

}

class Employee {
	private int id;
	private String name;
	private String role;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getRole() {
		return role;
	}

	public void setRole(String role) {
		this.role = role;
	}

	@Override
	public String toString() {
		return "Emp[" + id + "," + name + "," + role + "]";
	}
}

  • Первый шаг — создать сканер для CSV-файла и установить новую строку в качестве разделителя.
  • Затем для каждой строки, содержащей запись о сотруднике в формате CSV, проанализируйте ее, используя другой сканер и запятую в качестве разделителя. parseEmployeeData() анализирует каждую строку и создает объект Employee.
  • Наконец, мы добавляем объект сотрудника в список и печатаем его.

Вывод: [Emp[1, Джейн Доу, генеральный директор], Emp[2, Мэри Энн, технический директор], Emp[3, Джон Ли, финансовый директор]]

3. Пример регулярного выражения сканера Java

Допустим, у нас есть источник строк, и мы хотим обрабатывать только присутствующие в нем целые числа. Мы можем использовать сканер с нецифровым регулярным выражением, чтобы получить только целые числа в качестве токенов для их обработки.

//using regex to read only integers from a string source
String data = "1a2b345c67d8,9#10";
Scanner sc1 = new Scanner(data);

// setting non-digit regex as delimiter
sc1.useDelimiter("\\D");

while(sc1.hasNext()) {
	System.out.println(sc1.next());
}

// don't forget to close the scanner
sc1.close();

Выход:

1
2
345
67
8
9
10

Заключение

Java Scanner — это служебный класс для чтения пользовательского ввода или обработки простого синтаксического анализа исходного файла или строки на основе регулярных выражений. Но для реальных приложений лучше использовать синтаксические анализаторы CSV для анализа данных CSV, а не использовать класс Scanner для повышения производительности.

Ссылка: регулярное выражение в Java