Java - Entrada e Saída de Dados via Console (Programas em Modo Texto)

2020/08/18

Constantemente vejo pessoas postando problemas com programas que realizam a entrada de dados pelo teclado utilizando a classe Scanner.

Geralmente esses problemas estão relacionados ao uso indevido dos métodos nextInt, nextByte, nextDouble, nextFloat, nextInt, nextLong e nextShort.

Estes métodos não consomem o caractere de quebra de linha gerado ao pressionar ENTER no teclado e isso gera comportamentos indesejados, pois caso o método nextLine seja chamado após qualquer um desses outros métodos, ele simplesmente vai consumir a quebra de linha que ficou no buffer e vai retornar um String vazio.

A classe Scanner é uma ótima alternativa à classe DataInputStream ao ler arquivos ou streams de dados, mas é uma encrenca ao ler dados no console.

Tendo isto em vista, resolvi disponibilizar em meu GitHub a classe StdIO para encapsular o System.in e System.out do Java, facilitando a leitura e escrita no console.

A classe StdIO possui sobrecargas dos seguintes métodos de leitura e escrita:

    StdIO.readBoolean
    StdIO.readByte
    StdIO.readChar
    StdIO.readDouble
    StdIO.readFloat
    StdIO.readInt
    StdIO.readLong
    StdIO.readShort
    StdIO.readString

    StdIO.print
    StdIO.printf
    StdIO.println

Suas sobrecargas incluem a possibilidade de apresentar uma mensagem durante a leitura e também adicionar predicados que permitem a releitura no caso de valores inválidos.

Vejamos alguns exemplos a seguir:

Lendo um número inteiro:

    int numeroInteiro = StdIO.readInt();

Lendo um número inteiro maior que 10:

    int numeroInteiro = StdIO.readInt(numero -> numero > 10);

Lendo um número inteiro maior que 10 e menor que 20:

    int numeroInteiro = StdIO.readInt(numero -> numero > 10 && numero < 20);

Lendo um número real com mensagem:

    double numeroReal = StdIO.readDouble("Informe um número real: ");

Lendo um número real maior que 5.5 com mensagem:

    double numeroReal = StdIO.readDouble("Informe um número real maior que 5.5: ", numero -> numero > 5.5);

Lendo um número real maior que 4.5 e menor que 6.5 com mensagem:

    double numeroReal = StdIO.readDouble("Informe um número real maior que 4.5 e menor que 6.5: ", numero -> numero > 4.5 && numero < 6.5);

Lendo texto:

    String texto = StdIO.readString();

Lendo texto que não pode ser vazio:

    String textoDigitado = StdIO.readString(texto -> !texto.trim().isEmpty());

Lendo texto com mensagem:

    String textoDigitado = StdIO.readString("Digite seu nome: ");

Lendo texto de no máximo 15 caracteres e com mensagem:

    String textoDigitado = StdIO.readString("Digite seu nome (max 15 letras): ", texto -> texto.length() <= 15);

Lendo sexo com possibilidade entre m ou f:

    char sexo = StdIO.readChar(letra -> letra == 'm' || letra == 'f');

Lendo sexo com com mensagem:

    char sexo = StdIO.readChar("Digite o sexo: ['m' ou 'f'] ", letra -> letra == 'm' || letra == 'f');

As saídas de dados com a classe StdIO são idênticos à utilizar o System.out do Java, mas existem de forma a permitir utilizar uma única classe tanto para entrada quanto para a saída de dados.

Exemplos de saída:

    StdIO.println();

    StdIO.println("Qualquer coisa com quebra de linha");

    StdIO.print("Qualquer coisa sem quebra de linha");

    StdIO.printf("Valor real formatado com 2 casas: %.2f", 123.456789);

    StdIO.printf("Valor real formatado com 3 casas e quebra de linha: %.3f%n", 9876.54321);

É isso pessoal. A classe StdIO está disponível em meu GitHub para quem quiser. Espero que seja útil.