Перейти к основному содержимому

Java-сканер

· 6 мин. чтения

1. Обзор сканера

В этом кратком руководстве мы покажем, как использовать класс Java Scanner — для чтения ввода, поиска и пропуска шаблонов с разными разделителями.

2. Сканировать файл

Сначала — давайте посмотрим, как прочитать файл с помощью Scanner .

В следующем примере мы читаем файл, содержащий « Hello world », в токены:

@Test
public void whenReadFileWithScanner_thenCorrect() throws IOException{
Scanner scanner = new Scanner(new File("test.txt"));

assertTrue(scanner.hasNext());
assertEquals("Hello", scanner.next());
assertEquals("world", scanner.next());

scanner.close();
}

Обратите внимание, что метод next() возвращает здесь следующий токен String .

Также обратите внимание, как мы закрываем сканер, когда закончим его использовать.

3. Преобразование InputStream в строку

Далее — давайте посмотрим, как преобразовать InputStream в String с помощью Scanner :

@Test
public void whenConvertInputStreamToString_thenConverted()
throws IOException {
String expectedValue = "Hello world";
FileInputStream inputStream
= new FileInputStream("test.txt");

Scanner scanner = new Scanner(inputStream);
scanner.useDelimiter("A");

String result = scanner.next();
assertEquals(expectedValue, result);

scanner.close();
}

Как и в предыдущем примере, мы использовали Scanner для токенизации всего потока от начала до следующего регулярного выражения «A», которое соответствует полному вводу.

4. Сканер против BufferedReader

Теперь — давайте обсудим разницу между Scanner и BufferedReader — мы обычно используем:

  • BufferedReader , когда мы хотим прочитать ввод в строки
  • Сканер для чтения ввода в токены

В следующем примере мы читаем файл по строкам с помощью BufferedReader :

@Test
public void whenReadUsingBufferedReader_thenCorrect()
throws IOException {
String firstLine = "Hello world";
String secondLine = "Hi, John";
BufferedReader reader
= new BufferedReader(new FileReader("test.txt"));

String result = reader.readLine();
assertEquals(firstLine, result);

result = reader.readLine();
assertEquals(secondLine, result);

reader.close();
}

Теперь воспользуемся Scanner для чтения того же файла в токены:

@Test
public void whenReadUsingScanner_thenCorrect()
throws IOException {
String firstLine = "Hello world";
FileInputStream inputStream
= new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);

String result = scanner.nextLine();
assertEquals(firstLine, result);

scanner.useDelimiter(", ");
assertEquals("Hi", scanner.next());
assertEquals("John", scanner.next());

scanner.close();
}

Обратите внимание, как мы используем Scanner nextLine() API — для чтения всей строки .

5. Сканировать ввод из консоли с помощью нового сканера (System.in)

Далее — давайте посмотрим, как читать ввод из консоли с помощью экземпляра сканера :

@Test
public void whenReadingInputFromConsole_thenCorrect() {
String input = "Hello";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(input.getBytes()));

Scanner scanner = new Scanner(System.in);

String result = scanner.next();
assertEquals(input, result);

System.setIn(stdin);
scanner.close();
}

Обратите внимание, что мы использовали System.setIn(…) для имитации некоторого ввода, поступающего из консоли.

5.1. API следующей строки ()

Этот метод просто возвращает строку в текущей строке:

scanner.nextLine();

Это считывает содержимое текущей строки и возвращает его, за исключением любого разделителя строк в конце — в данном случае — символа новой строки.

После прочтения содержимого Scanner устанавливает свою позицию на начало следующей строки. Важно помнить, что API nextLine() использует разделитель строк и перемещает позицию сканера на следующую строку .

Так что в следующий раз, если мы будем читать через Scanner , мы будем читать с начала следующей строки.

5.2. API следующегоInt()

Этот метод сканирует следующий токен ввода как целое число :

scanner.nextInt();

API считывает целочисленный токен, доступный следующим.

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

Итак, если у нас есть серия операций, где первая операция — это scan.nextInt() , а затем scan.nextLine() , и в качестве входных данных, если мы указываем целое число и нажимаем разрыв строки, обе операции будут выполнены.

API nextInt() использует целое число, а API nextLine() использует разделитель строк и помещает Scanner в начало следующей строки.

6. Подтвердите ввод

Теперь давайте посмотрим, как проверить ввод с помощью сканера . В следующем примере мы используем метод сканера hasNextInt() , чтобы проверить, является ли ввод целым числом:

@Test
public void whenValidateInputUsingScanner_thenValidated()
throws IOException {
String input = "2000";
InputStream stdin = System.in;
System.setIn(new ByteArrayInputStream(input.getBytes()));

Scanner scanner = new Scanner(System.in);

boolean isIntInput = scanner.hasNextInt();
assertTrue(isIntInput);

System.setIn(stdin);
scanner.close();
}

7. Сканировать строку

Далее — давайте посмотрим, как сканировать строку с помощью Scanner :

@Test
public void whenScanString_thenCorrect()
throws IOException {
String input = "Hello 1 F 3.5";
Scanner scanner = new Scanner(input);

assertEquals("Hello", scanner.next());
assertEquals(1, scanner.nextInt());
assertEquals(15, scanner.nextInt(16));
assertEquals(3.5, scanner.nextDouble(), 0.00000001);

scanner.close();
}

Примечание. Метод nextInt(16) считывает следующий токен как шестнадцатеричное целое число.

8. Найдите шаблон

Теперь давайте посмотрим, как найти шаблон с помощью сканера .

В следующем примере мы используем findInLine() для поиска токена, соответствующего заданному шаблону , во всем вводе:

@Test
public void whenFindPatternUsingScanner_thenFound() throws IOException {
String expectedValue = "world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);

String result = scanner.findInLine("wo..d");
assertEquals(expectedValue, result);

scanner.close();
}

Мы также можем искать шаблон в определенном домене, используя findWithinHorizon() , как в следующем примере:

@Test
public void whenFindPatternInHorizon_thenFound()
throws IOException {
String expectedValue = "world";
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);

String result = scanner.findWithinHorizon("wo..d", 5);
assertNull(result);

result = scanner.findWithinHorizon("wo..d", 100);
assertEquals(expectedValue, result);

scanner.close();
}

Обратите внимание, что горизонт поиска — это просто количество символов , в пределах которого выполняется поиск.

9. Пропустить шаблон

Далее — давайте посмотрим, как пропустить шаблон в сканере . Мы можем пропустить токены, соответствующие определенному шаблону, при чтении ввода с помощью Scanner .

В следующем примере мы пропускаем токен « Hello », используя метод Skip() сканера : ``

@Test
public void whenSkipPatternUsingScanner_thenSkipped()
throws IOException {
FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);

scanner.skip(".e.lo");

assertEquals("world", scanner.next());

scanner.close();
}

10. Изменить разделитель сканера

Наконец – давайте посмотрим, как изменить разделитель Scanner . В следующем примере мы меняем разделитель сканера по умолчанию на « o »:

@Test
public void whenChangeScannerDelimiter_thenChanged()
throws IOException {
String expectedValue = "Hello world";
String[] splited = expectedValue.split("o");

FileInputStream inputStream = new FileInputStream("test.txt");
Scanner scanner = new Scanner(inputStream);
scanner.useDelimiter("o");

assertEquals(splited[0], scanner.next());
assertEquals(splited[1], scanner.next());
assertEquals(splited[2], scanner.next());

scanner.close();
}

Мы также можем использовать несколько разделителей. В следующем примере мы используем обе запятые « , » и «тире» «в качестве разделителей для сканирования файла, содержащего « Джон, Адам-Том »:

@Test
public void whenReadWithScannerTwoDelimiters_thenCorrect()
throws IOException {
Scanner scanner = new Scanner(new File("test.txt"));
scanner.useDelimiter(",|-");

assertEquals("John", scanner.next());
assertEquals("Adam", scanner.next());
assertEquals("Tom", scanner.next());

scanner.close();
}

Примечание. Разделителем Scanner по умолчанию `` является пробел.

11. Заключение

В этом руководстве мы рассмотрели несколько реальных примеров использования Java Scanner .

Мы научились читать ввод из файла, консоли или строки с помощью Scanner ; мы также узнали, как найти и пропустить шаблон с помощью сканера , а также как изменить разделитель сканера .

Реализацию этих примеров можно найти на GitHub .