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.