Java Scanner para lectura de datos

La clase Scanner está disponible a partir de Java 5 y facilita la lectura de datos en los programas Java.
Primero veremos varios ejemplos de lectura de datos en Java con Scanner y después explicaremos en detalle como funciona.
Para utilizar Scanner en el programa tendremos que hacer lo siguiente:
1. Escribir el import
La clase Scanner se encuentra en el paquete java.util por lo tanto se debe incluir al inicio del programa la instrucción:
import java.util.Scanner;
2. Crear un objeto Scanner
Tenemos que crear un objeto de la clase Scanner asociado al dispositivo de entrada.
Si el dispositivo de entrada es el teclado escribiremos:
Scanner sc = new Scanner(System.in);
Se ha creado el objeto sc asociado al teclado representado por System.in
Una vez hecho esto podemos leer datos por teclado.
Ejemplos de lectura:
Para leer podemos usar el método nextXxx() donde Xxx indica en tipo, por ejemplo nextInt() para leer un entero, nextDouble() para leer un double, etc.

Ejemplo de lectura por teclado de un número entero:
int n;
System.out.print("Introduzca un número entero: ");
n = sc.nextInt();

Ejemplo de lectura de un número de tipo double:
double x;
System.out.print("Introduzca número de tipo double: ");
x = sc.nextDouble();

Ejemplo de lectura de una cadena de caracteres:
String s;
System.out.print("Introduzca texto: ");
s = sc.nextLine();

Ejemplo de programa Java con lectura de datos con Scanner:
El programa pide que se introduzca el nombre de la persona y lo muestra por pantalla. A continuación lee por teclado el radio de una circunferencia de tipo double y muestra su longitud. Además lee un entero y muestra su cuadrado.

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {     
           Scanner sc = new Scanner(System.in);  //crear un objeto Scanner
           String nombre;
           double radio;
           int n;
           System.out.print("Introduzca su nombre: ");       
           nombre = sc.nextLine();  //leer un String
           System.out.println("Hola " + nombre + "!!!");
           System.out.print("Introduzca el radio de la circunferencia: ");
           radio = sc.nextDouble(); //leer un double
           System.out.println("Longitud de la circunferencia: " + 2*Math.PI*radio);
           System.out.print("Introduzca un número entero: ");
           n = sc.nextInt(); //leer un entero
           System.out.println("El cuadrado es: " + Math.pow(n,2));
     }
}

Funcionamiento la clase Java Scanner.
De forma resumida podemos decir que cuando se introducen caracteres por teclado, el objeto Scanner toma toda la cadena introducida y la divide en elementos llamados tokens.
El carácter predeterminado que sirve de separador de tokens es el espacio en blanco.
Por ejemplo, si introducimos:
Esto es un ejemplo, lectura de datos.
Scanner divide la cadena en los siguientes tokens:
Esto
es
un
ejemplo,
lectura
de
datos.

Si introducimos la cadena:

12 20.001 Lucas w

Los tokens que se crean son:

12
20.001
Lucas
w

A continuación, utilizando los métodos que proporciona la clase Scanner se puede acceder a esos tokens y trabajar con ellos en el programa.

Ya hemos visto el método nextXxx(). Además la clase Scanner proporciona otros métodos, algunos de los métodos más usados son:

METODO
DESCRIPCIÓN
nextXxx()
Devuelve el siguiente token como un tipo básico. Xxx es el tipo. Por ejemplo, nextInt() para leer un entero, nextDouble para leer un double, etc.
next()
Devuelve el siguiente token como un String.
nextLine()
Devuelve la línea entera como un String. Elimina el final \n del buffer
hasNext()
Devuelve un boolean. Indica si existe o no un siguiente token para leer.
hasNextXxx()
Devuelve un boolean. Indica si existe o no un siguiente token del tipo especificado en Xxx, por ejemplo hasNextDouble()
useDelimiter(String)
Establece un nuevo delimitador de token.

Cómo limpiar el buffer de entrada en Java
Cuado en un programa se leen por teclado datos numéricos y datos de tipo carácter o String debemos tener en cuenta que al introducir los datos y pulsar intro estamos también introduciendo en el buffer de entrada el intro.
Es decir, cuando en un programa introducimos un datos y pulsamos el intro como final de entrada, el carácter intro también pasa al buffer de entrada.
Buffer de entrada si se introduce un 5: 5\n
En esta situación, la instrucción:

n = sc.nextInt();

Asigna a n el valor 5 pero el intro permanece en el buffer
Buffer de entrada después de leer el entero: \n

Si ahora se pide que se introduzca por teclado una cadena de caracteres:

System.out.print("Introduzca su nombre: ");       
nombre = sc.nextLine();  //leer un String

El método nextLine() extrae del buffer de entrada todos los caracteres hasta llegar a un intro y elimina el intro del buffer.
En este caso asigna una cadena vacía a la variable nombre y limpia el intro. Esto provoca que el programa no funcione correctamente, ya que no se detiene para que se introduzca el nombre.

Solución:

Se debe limpiar el buffer de entrada si se van a leer datos de tipo carácter a continuación de la lectura de datos numéricos.

La forma más sencilla de limpiar el buffer de entrada en Java es ejecutar la instrucción:

sc.nextLine();

Lo podemos comprobar si cambiamos el orden de lectura del ejemplo y leemos el nombre al final:

import java.util.Scanner;
public class JavaApplication335 {
    public static void main(String[] args) {     
           Scanner sc = new Scanner(System.in);
           String nombre;
           double radio;
           int n;        
           System.out.print("Introduzca el radio de la circunferencia: ");
           radio = sc.nextDouble();
           System.out.println("Longitud de la circunferencia: " + 2*Math.PI*radio);
           System.out.print("Introduzca un número entero: ");
           n = sc.nextInt();
           System.out.println("El cuadrado es: " + Math.pow(n,2));
           System.out.print("Introduzca su nombre: ");       
           nombre = sc.nextLine();  //leemos el String después del double
           System.out.println("Hola " + nombre + "!!!");
     }
}

Si lo ejecutamos obtendremos:
Introduzca el radio de la circunferencia: 34
Longitud de la circunferencia: 213.62830044410595
Introduzca un número entero: 3
El cuadrado es: 9.0
Introduzca su nombre: Hola !!!

Comprobamos que no se detiene para pedir el nombre.
La solución es escribir la instrucción
sc.nextLine();
después de la lectura del int y antes de leer el String:

import java.util.Scanner;
public class JavaApplication335 {
    public static void main(String[] args) {
           Scanner sc = new Scanner(System.in);
           String nombre;
           double radio;
           int n;        
           System.out.print("Introduzca el radio de la circunferencia: ");
           radio = sc.nextDouble();
           System.out.println("Longitud de la circunferencia: " + 2*Math.PI*radio);
           System.out.print("Introduzca un número entero: ");
           n = sc.nextInt();
           System.out.println("El cuadrado es: " + Math.pow(n,2));
           sc.nextLine();
           System.out.print("Introduzca su nombre: ");       
           nombre = sc.nextLine();
           System.out.println("Hola " + nombre + "!!!");
     }
}

Ahora la ejecución es correcta:
Introduzca el radio de la circunferencia: 23
Longitud de la circunferencia: 144.51326206513048
Introduzca un número entero: 5
El cuadrado es: 25.0
Introduzca su nombre: Lucas
Hola Lucas!!!

Si quieres ver más ejemplos de entrada de datos en Java con Scanner los tienes en este enlace
Ejercicios Básicos en Java


70 comentarios:

  1. Excelente!!!!1, me ayudo bastante

    ResponderEliminar
  2. ~Me ayudo mucho en esto muchas gracias^^

    ResponderEliminar
  3. Gracias. Me alegro de que os sea útil.

    ResponderEliminar
    Respuestas
    1. excelenteeeeee !! gracias por este aporte

      Eliminar
    2. que tal para poder limpiar la consola, he utilizado getRuntime, el System.out.print("\033[H\033[2J");
      System.out.flush(); y nada alguna otra solucion

      Eliminar
    3. como ago para desarrolar un programa que permita leer el nombre de una persona y como resultado muestre u saludo

      Eliminar
    4. import java.util.Scanner;
      public class JavaApplication335 {
      public static void main(String[] args) {
      Scanner sc = new Scanner(System.in);
      String nombre;
      System.out.print("Introduzca su nombre: ");
      nombre = sc.nextLine();
      System.out.println("Hola " + nombre + "!!!");
      }
      }

      En el código de arriba estaba jejej

      Eliminar
  4. ¡Muchas gracias!

    Ese ".nextLine()" después de un ".nextInt()" me ha salvado de implementar soluciones más originales ;-)

    ResponderEliminar
  5. Pff!! tienes talentoo para esto! nunca ví un Blog como este! sigue así, pon más temas por fa (:

    ResponderEliminar
  6. no me ayudo en nada! -.-

    ResponderEliminar
    Respuestas
    1. por pendejo!!! y me vale madres... .l.(-.-).l.

      Eliminar
  7. Muy buena informacion,,, buen apunte...

    ResponderEliminar
  8. Hola gracias por la información. Tengo una duda en que casos hay la necesidad de usar más de un objeto Scanner.

    ResponderEliminar
    Respuestas
    1. Por ejemplo, cuando vas a leer datos por teclado y además quieres leer el contenido de un fichero de texto. Puedes usar un objeto Scanner para cada cosa.

      Eliminar
  9. y no hay ningun metodo como sc.nextChar();???

    ResponderEliminar
  10. Gracias, tenía problemas con un nextLine() que al parecer no se ejecutaba, con esta info lo pude resolver.

    ResponderEliminar
  11. como hago usando la clase scanner , por ejemplo , para Imponerle que me ponga tal nombre , y que la persona no lo elija ?

    ResponderEliminar
  12. Excelente amigo de verdad gracias muy buena explicacion!

    ResponderEliminar
  13. PORQUE AL REALIZAR ESTO:
    System.out.print("Introduzca su nombre: ");
    nombre = sc.nextLine();
    System.out.println("Hola " + nombre + "!!!");

    Y AL IMPRIMIR nombre no me imprime la letra ñ?

    ResponderEliminar
    Respuestas
    1. porque ñ es de caracter especial

      Eliminar
  14. muy buen post gracias muchacho Dios te bendiga y te siga dando conocimiento para compartir fue de gran ayuda (:

    ResponderEliminar
  15. Gracias me ha servido de mucho...

    ResponderEliminar
  16. Muchas gracias por los comentarios, espero que os haya servido de ayuda para poder entender mejor el funcionamiento de la clase Scanner

    ResponderEliminar
  17. GRACIASSSSSSSSSSSS mas que util

    ResponderEliminar
  18. hola como puedo hacer si quiero hacer un ciclo para introducir 10 datos de personas con for y al comenzar la 2da vuelta me salta la segunda linea y evita introducir el nombre nuevamente? gracias

    System.out.println("Enter the Name of your " + i + " Seller: ");
    seller[i] = keyboard.nextLine();
    System.out.println("Enter your Sex('F' Female or 'M' Male: ");
    sex[i] = keyboard.next().charAt(0);
    System.out.println("How many T-shirt have the person sold?: ");
    tshirt[i] = keyboard.nextInt();
    quien tenga info acerca de este sera bien recibida,
    gracias.

    ResponderEliminar
    Respuestas
    1. Yo creo que no le pondría el nextLine sino solo next(); porque seller debe ser string no?

      Eliminar
    2. Si en el campo seller se lee nombre y apellido separado por espacio, next() solo obtiene el nombre dejando el apellido para elo siguiente next(). seller hay que leerlo con nextLine(). La solución paralo que planteas es escribir la instrución keyboard.nextLine(); justo después de la instrucción
      tshirt[i] = keyboard.nextInt();
      La explicación la tienes en esta entrada en el apartado: como limpiar el buffer en Java

      Eliminar
  19. Grande!!! Me ayudó mucho ya que estaba leyendo datos y strings y no entendía por qué se saltaba el string :-D

    ResponderEliminar
    Respuestas
    1. Daniel me alegro de que te haya servido de ayuda. A ti y a los demás que también han comentado antes que tenían el mismo problema de lectura. Es algo que nos ha pasado a todos y hasta que no lo descubres es muy frustrante porque en apariencia el código está bien pero la lectura no se hace de forma correcta.
      Un saludo y espero que sigas visitando el blog

      Eliminar
  20. hola muy buen post, oye tengo una duda cuando se usa br en cambio de sc para que es??

    ResponderEliminar
  21. gracias por tu explicacion esta muy completa me sirvio mucho

    ResponderEliminar
  22. en el double x; que declaraste , no lo usaste bien, es x.sc.nextDouble(); / y no n.sc.nextDouble();
    declaraste "x" para el double , no "n" ese era del int del ejemplo de arriba del double

    ResponderEliminar
    Respuestas
    1. Gracias por avisar, ya está corregido. Cosas del Copy-Paste

      Eliminar
  23. Para evitar escribir una línea de más (sc.nextLine()), simplemente hacemos la lectura con next, es decir:

    nombre=sc.next();

    ResponderEliminar
  24. en efecto haciendo nombre=sc.next(); funciona y no hay que hacer limpieza.

    ResponderEliminar
    Respuestas
    1. El problema de leer con next() es que si se introduce más de una palabra solo se toma la primera.

      Eliminar
    2. Eres el unico que me a podido explicar con claridad el Scanner gracias ni mi profesora de programacion sabe explicarla con bien solo da un papel con trabajo y que se encomiende uno a Dios porque tiene que sacarsela de la manga .

      Eliminar
    3. Me alegro de que te haya servido de ayuda. Gracias por seguir el blog ;)

      Eliminar
  25. Has resuelto la duda exacta que tenia con esta clase. Gracias

    ResponderEliminar
  26. Otra opción (para el problema con los nextInt() ) sería usar por ejemplo:
    int x = Integer.parseInt(sc.nextLine());
    De esta forma te lee la linea entera (descartando el retorno de carro) y te lo transforma a un int.

    ResponderEliminar
  27. si declaro una variable int, y en la consola se me pide un entero; pero si escribo cualquier otra cosa me truena el programa, metiendole un try- catch me permite correrlo pero se para el programa, si yo quisiera meterlo en un ciclo y terminar el programa hasta que se me ingrese un entero. ¿cómo podria hacerlo? algúna pista? Gracias.

    ResponderEliminar
    Respuestas
    1. puedes hacerlo con un do .. while
      boolean repetir;
      do{
      try{
      repetir = false;
      System.out.print("Introduce un número entero: ");
      n = sc.nextInt();
      System.out.println("Número introducido: " + n);
      }catch(InputMismatchException e){
      sc.nextLine();
      repetir = true;
      System.out.println("Debe introducir un número entero " + e.toString());
      }
      }while(repetir);

      Eliminar
    2. De nada Aaron, espero que te sirva. Saludos

      Eliminar
  28. Respuestas
    1. Gracias Juan Luis. Espero que te haya sido útil.

      Eliminar
  29. tengo unas dudas donde te puedo contactar?

    ResponderEliminar
  30. Excelente aporte sinceramente [^^] Noob to java Here xd

    ResponderEliminar
    Respuestas
    1. Gracias Adrian, en nada de noob to pro xd

      Eliminar
  31. q la fuerza del pan te acompañe a todos lados

    ResponderEliminar
  32. Que tal estoy utilizando la clase Scanner pero quiero limpiar la pantalla; he utilizado Runtime.getRuntime().exec(), el System.out.print("\033[H\033[2J");System.out.flush();
    y nada alguna otra solucion saludos

    ResponderEliminar
  33. 1. Solicite al usuario la temperatura máxima del mes y la temperatura medida hoy, actualice el valor de la temperatura máxima si la temperatura leída hoy es mayor que la temperatura máxima.

    ResponderEliminar
  34. Buenísimo tu blog sigue así... Trata de subir mas informaciones como por ejemplo los tipos de librerías que se usan en java y sus funcionalidades...

    ResponderEliminar
  35. Buenísimo tu blog sigue así... Trata de subir mas informaciones como por ejemplo los tipos de librerías que se usan en java y sus funcionalidades...

    ResponderEliminar
  36. Me encantó tu explicación. Muy útil gracias!!!

    ResponderEliminar
  37. Buenas tardes

    Estoy buscando el codigo que me permita utilizar un periférico especifico, un scanner, con el fin de digitalizar unos formularios.

    ResponderEliminar
  38. ¿Como colocas el scanner en la encapsulación de datos es decir en el método establecer? saludos

    ResponderEliminar
  39. entonces hay el limpiar el buffer cada vez que entra un entero y después se quiere leer un string?

    ResponderEliminar