====== Clase Scanner ======
La clase Scanner está disponible desde Java 5, y ofrece métodos para leer datos introducidos por el usuario desde la entrada standard (teclado).
A diferencia de la clase String, la clase Scanner se encuentra en el paquete ''java.util''.
===== Importar la clase Scanner =====
Como hemos dicho, para poder usar la clase Scanner debemos importarla desde su paquete. La sentencia ''import'' siempre debe ir al principio del código, después de la sentencia ''package'':
package nombrePaquete; //si mi clase está dentro de un paquete
import java.util.Scanner;
===== Crear un objeto Scanner =====
Para poder usarla debemos crear un objeto de la clase Scanner. Lo asociamos a la entrada standard:
Scanner input = new Scanner(System.in);
//Cerrar siempre el scanner
input.close();
**IMPORTANTE**: El método ''close()'' no cierra el Scanner, sino que cierra el flujo de entrada ''System.in''. Cualquier lectura posterior desde ese flujo (System.in), lanzará una excepción.
==== Tipos de flujos de entrada ====
''System.in'' representa la entrada standard, el teclado, del mismo modo que ''System.out'' representa la salida standard, la consola.
Pero Scanner también puede leer desde un ''String'', o desde un fichero de texto, objeto ''File'' .
=====Leer tipos de datos=====
La clase Scanner tiene métodos para leer directamente los siguientes tipos de datos:
''String'', ''short'', ''byte'', ''int'', ''float'', ''long'', ''double'' y ''boolean''.
int entero = input.nextInt();
boolean booleano = input.nextBoolean();
double real = input.nextDouble();
String cadena = input.nextLine(); //Lee caracteres hasta encontrar un intro
El método** ''nextLine()'' ** lee todos los caracteres que haya en el buffer de entrada, hasta encontrar un carácter de ''intro''.
No podemos leer un ''char'', pero podemos leerlo como String y coger el primer caracter.
char caracter = input.nextLine().charAt(0);
//Que es lo mismo que:
String cadena = input.nextLine();
char caracter = cadena.charAt(0);
Con el método ''next()'' podemos obtener un String con la siguiente palabra, separada por espacios. **No se recomienda su uso para leer Strings**.
//Introducimos por teclado el texto -> "Cadena de 4 palabras"
String palabra1 = input.next(); -> obtengo "Cadena"
String palabra2 = input.next(); -> obtengo "de"
String cadena = input.nextLine(); -> obtengo "4 palabras";
===== Funcionamiento interno =====
De forma resumida, cuando introducimos texto por teclado, el objeto Scanner divide la cadena de texto completa, en elementos llamados ''tokens'' y los guarda en su ''buffer de lectura ó entrada''.
El caracter por defecto para separar los tokens es el ' ' (espacio en blanco).
Ejemplo:
* Introduzco la cadena ''12 20.001 Lucas w'' y pulso intro.
* Scanner crea la siguiente lista de tokens:
* ''12''
* ''20.001''
* ''Lucas''
* ''w''
A continuación puedo acceder a esos ''tokens'' almacenados en el buffer de lectura, a través de los distintos métodos.
//Introduzco por teclado una cadena formada por 5 "tokens"
//Por ejemplo la cadena: "4 o 5 palabras cortas"
int num = input.nextInt(); //leo el "4" como tipo int
String cadena1 = next(); //leo la "o" como tipo String
String cadena2 = next(); //leo el "5" como tipo String
String cadena3 = nextLine(); //leo hasta encontrar un intro: "palabras cortas"
===== Limpiar buffer de lectura =====
Cada vez que introducimos datos por teclado terminamos presionando ''intro''.
Scanner guarda en el //buffer de entrada// todos los caracteres introducidos, incluido la tecla ''intro''.
Buffer de entrada al introducir el numero 53:
// Estado del buffer de entrada:
"53\n" -> \n representa la tecla enter
int numero = input.nextInt();
//Estado del buffer de entrada después de leer el int
"\n"
String cadena = input.nextLine();
//Leerá hasta encontrar el enter, y obtenemos una cadena vacía "".
Siempre que vaya a leer un String después de haber leido un número, **debemos //limpiar// el buffer de entrada** antes de leer el String, llamando al método:
input.nextLine();
===== Comprobar estado del buffer =====
''Scanner'' también contiene algunos métodos para comprobar si quedan datos en el flujo de entrada (buffer). Esto es realmente interesante **cuando el flujo de entrada son datos contenidos en un fichero**, y desconocemos el número de lineas.
Los siguientes métodos devuelven ''true'' mientras queden datos en el flujo de entrada:
^Metodo^ Función ^
|hasNextInt() | Comprueba si quedan enteros |
|hasNextLine() | Comprueba si quedan Strings |
|hasNextFloat() | Comprueba si quedan valores float |
|hasNextDouble() | Comprueba si quedan valores double |
|hasNextShort() | Comprueba si quedan enteros cortos |
|hasNext() | Comprueba si quedan palabras (//tokens//)|
|hasNextBoolean() | Comprueba si quedan valores booleanos |
Podemos usarlo con un bucle while, para leer mientras quedan valores.
while(input.hasNextLine(){
String cadena = input.nextLine();
//proceso datos leidos
}
===== Leer número de coma flotante con distinta notación =====
Los lenguajes de programación usan por defecto la notación americana a la hora de trabajar con números decimales:
float decimalFloat = 3.13F; //literal de float
double decimalDouble = 4.345; //literal de double
Pero a la hora de leer, Scanner accede a la configuración regional de nuestro sistema. En España se usa la notación francesa (''34,6'').
Si queremos que nuestro Scanner lea los decimales con un ''.'' en lugar de con una '','', debemos indicarle que usamos la configuración local americana.
System.out.println(input.locale());
input.setLocale(Locale.US);
----
{{ vimeo>295702626?medium }}
----
(c) {{date> %Y}} Fernando Valdeón