Java Scanner

Java Scanner

1. Visão geral

Neste tutorial, ilustraremos como usarJava Scanner para ler a entrada e encontrar e pular padrões com diferentes delimitadores.

2. Digitalizar um arquivo

Primeiro - vamos ver como ler um arquivo usandoScanner. No exemplo a seguir - lemos que um arquivo contém “Hello world” em tokens usandoScanner:

@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();
}

Nota: O métodoScannernext() retorna o próximo tokenString.

3. ConvertaInputStream emString

A seguir - vamos ver como converter umInputStream em umString usandoScanner:

@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();
}

Nota: No exemplo anterior, enganamos oScanner para tokenizar todo o fluxo do início até a próxima regex “A” (que corresponde ao início da entrada).

4. Scanner vs. BufferedReader

Agora - vamos discutir a diferença entreScannereBufferedReader - geralmente usamos:

  • BufferedReader quando queremos ler a entradainto lines

  • Scanner para ler a entradainto tokens

No exemplo a seguir - estamos lendo um arquivo em linhas usandoBufferedReader:

@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();
}

Agora, vamos usarScanner para ler o mesmo arquivo em tokens:

@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();
}

Observação: também podemos usar a APIScannernextLine() para ler a linha inteira.

5. Verificar entrada do console usandoNew Scanner(System.in)

A seguir - vamos ver como ler a entrada do Console usandoScanner:

@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();
}

Observe que usamosSystem.setIn(…) para simular alguma entrada vinda do console.

5.1. APInextLine()

Este método simplesmente retorna a string na linha atual:

scanner.nextLine();

Isso lê o conteúdo da linha atual e o retorna, exceto para qualquer separador de linha no final - nesse caso - o novo caractere de linha.

Depois de ler o conteúdo,Scanner define sua posição para o início da próxima linha. O ponto importante a lembrar é que onextLine() API consumes the line separator and moves the position of the Scanner to the next line.

Então, da próxima vez, se lermosScanner, estaremos lendo desde o início da próxima linha.

5.2. APInextInt()

Este método verifica o próximo token da entrada como umint:

scanner.nextInt();

A API lê o token inteiro disponível a seguir. Nesse caso, se o próximo token for um inteiro e após o inteiro houver um separador de linha, lembre-se sempre de quenextInt() will not consume the line separator. Instead, the position of the scanner will be the line separator itself.

Portanto, se tivermos uma série de operações, onde a primeira operação éscanner.nextInt()escanner.nextLine()e como entrada, se fornecermos um inteiro e pressionarmos a quebra de linha, ambas as operações serão executadas.

A APInextInt() consumirá o inteiro e a APInextLine() consumirá o separador de linha e colocaráScanner no início da próxima linha.

6. Validar entrada

Agora - vamos ver como validar a entrada usando umScanner. No exemplo a seguir - usamos o métodoScannerhasNextInt() para verificar se a entrada é um valor inteiro:

@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. Digitalize umString

A seguir - vamos ver como escanearString usandoScanner:

@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();
}

Observação: o métodonextInt(16) lê o próximo token como um valor inteiro hexadecimal.

8. EncontrePattern

Agora - vamos ver como encontrar umPattern usandoScanner.

No exemplo a seguir - usamosfindInLine() asearch for a token that matches the given Pattern em toda a entrada:

@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();
}

Também podemos pesquisar umPattern no domínio específico usandofindWithinHorizon() como no exemplo a seguir:

@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();
}

Observe que osearch horizon is simply the number of characters dentro do qual a pesquisa é realizada.

9. PularPattern

A seguir - vamos ver como pularPattern emScanner. Podemos pular os tokens que correspondem a um padrão específico ao ler a entrada usandoScanner.

No exemplo a seguir - pulamos o token “Hello” usando o métodoScannerskip():

@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. Alterar o Delimitador deScanner

Finalmente - vamos ver como alterar o delimitadorScanner. No exemplo a seguir - mudamos o delimitadorScanner padrão para “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();
}

Também podemos usar vários delimitadores. No exemplo a seguir - usamos a vírgula “,” e o traço ”” como delimitadores para verificar um arquivo que contém “John,Adam-Tom“:

@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();
}

Nota: Odefault Scanner delimiter é um espaço em branco.

11. Conclusão

Neste tutorial, examinamos vários exemplos do mundo real usandoJava Scanner.

Aprendemos como ler a entrada do arquivo, console ouString usandoScanner; também aprendemos como localizar e pular um padrão usandoScanner - e também como alterar o delimitadorScanner.

A implementação desses exemplos pode ser encontradaover on GitHub - este é um projeto baseado em Maven, portanto, deve ser fácil de importar e executar como está.