domingo, 29 de enero de 2012

Clase Scanner en Java

La clase Scanner nos facilita mucho la tarea de obtención de datos desde diferentes fuentes.


Obtener datos desde el teclado

Una de las utilidades de la clase Scanner es la obtención de datos tecleados finalizando con un "enter".

Ejemplo:

import java.util.Scanner; // se importa la clase Scanner



 class Ejemplo {

 
 public static void main(String arg[]){
  
  String variableString;
  
  Scanner entrada=new Scanner(System.in);// se declara e inicializa una instancia  de la clase Scanner.
  
  System.out.print("Ingrese un texto: ");
  
  variableString = entrada.next();
  
  System.out.println("Texto ingresado: "+variableString);
  
 }
 
}


En el código anterior se importa la clase Scanner, posteriormente se declara una instancia de la misma llamada "entrada" y se inicializa pasando como parámetro un objeto InputStream ,
el cual es devuelto por la clase System con ayuda de su método in. Luego vemos como se imprime el aviso correspondiente del tipo de datos que se va a pedir y se guarda todo lo que se digíte en la variable "variableString", hasta que se teclee un enter.
Y todo se logra por medio del objeto Scanner llamado "entrada" y su método next().

De igual manera un objeto Scanner ofrece otros métodos que permiten recibir diferentes tipos:

import java.util.Scanner;



 class Ejemplo {

 
 public static void main(String arg[]){
  
  int variableEntero;
  float variableFloat;
  
  
  Scanner entrada=new Scanner(System.in);
  
  System.out.print("Ingrese un entero: ");
  
  variableEntero = entrada.nextInt();
  
  System.out.println("Entero ingresado: "+variableEntero);
  
  System.out.print("Ingrese un float: ");
  
  variableFloat = entrada.nextFloat();
  
  System.out.println("float ingresado: "+variableFloat);
  
 }
 
}





Obtener datos desde un archivo



La forma de obtener el contenido de un archivo con la clase Scanner es sin duda muy limpia, lo que cambia son los parámetros que se pasan al constructor, esta vez sera un objeto File:

    Scanner entrada=new Scanner(System.in);
    long numero=-1;
  
    try
    {
         entrada = new Scanner(new File("ruta_a_miArchivo/miArchivo"));

         while (entrada.hasNextLong()) 
         {
            numero = entrada.nextLong();
         }
        
        entrada.close();        
    
    } 
    catch (FileNotFoundException e)
    {
        e.printStackTrace();
    }
       
   System.out.println(" numero: "+numero);




En el código anterior se accede al contenido del archivo "miArchivo", el cual es un número desconocido.
El bloque try captura la excepción resultante en caso de que no exista dicho archivo,
y el while se encarga de asignar el contenido del archivo a la variable "numero", pero solo si ese archivo no esta vacío, es decir evita una excepción del tipo "NoSuchElementException".
Cabe aclarar que si el archivo tiene extensión como por ejemplo .txt , esta también se debe especificar en la ruta.



Ahora, en caso de nuestro archivo de ejemplo "miArchivo" tuviese varias lineas, como por ejemplo:

nombre: stivenson
lugar: Cúcuta Colombia
telefono: 256254

entonces, se podría utilizar los métodos nextLine y hasNextine, de la siguiente manera:

   
           
       Scanner entrada=new Scanner(System.in);
       String[] datos=new String[3];
       int indiceVector=0;
    
 try 
 {
    entrada = new Scanner(new File( "ruta_a_miArchivo/miArchivo"));

    while (entrada.hasNextLine()) 
    {
       datos[indiceVector++] = entrada.nextLine();
    }

    entrada.close();

 } 
 catch (FileNotFoundException e)
        {
    e.printStackTrace();
        }
       
       
 for(int i = 0 ; i < 3 ; i++ )
 {
    System.out.println(datos[i]);  
 }
       
       


En el código anterior se guarda cada una de las lineas del archivo en las posiciones del vector "datos" que posteriormente se imprimen en un for.


Y aquí no acaba todo, en el siguiente ejemplo vamos a obtener datos pero especificando un delimitador, supongamos que ahora nuestro archivo "miArchivo" tiene este contenido:

cantidad: 26565 cantidad: 3262625 cantidad: 2x10^4 cantidad: 121400001


y supongamos que solo queremos traer los números, para ello vamos a fijar delimitadores, algo que es posible y sin duda muy útil:

   Scanner entrada=new Scanner(System.in);
   String[] datos=new String[4];
   int indiceVector=0;
    
  try 
  {
   entrada =
   new Scanner(new File("ruta_a_miArchivo/miArchivo"))
   .useDelimiter("\\s*cantidad:\\s*");

 while (entrada.hasNext()) 
 {
     datos[indiceVector++] = entrada.next();
 }

   entrada.close();
  }
  catch (FileNotFoundException e)
  {
   e.printStackTrace();
  }
       
    
  for(int i = 0 ; i < 4 ; i++ )
  {
   System.out.println(datos[i]);  
  }
       
       


En el código anterior se obtienen los cuatro números del archivo y cada uno de estos se almacena en una posición del vector. Al delimitador (método useDelimiter) se le da como parámetro: "\\s*cantidad:\\s*".
Este parametro indica muchas cosas, primero están los signos "\\s*" los cuales indican que el delimitador puede empezar con cero o muchos espacios después se indica que va a estar seguido de la palabra "cantidad:" que a su vez va a estar seguida por cero o muchos espacios.

El carácter "\s" indica que se imprima un espacio, pero nosotros no queremos imprimir solo indicar, por eso le antecedemos el otro contraes-las: "\\s"; El signo "*" es el que indica que pueden haber cero o muchos de esos espacios, si tuviéramos que tratar con archivos de varias lineas, entonces sin duda tendríamos que trabajar con: "\n" en nuestros delimitadores.
En fin, el código anterior después de su ejecución imprime lo siguiente:

26565
3262625
2x10^4
12140001


Como se puede observar el delimitador nos ayuda a omitir ciertas partes del contenido que tengan un patrón en especifico, es decir fijar un separador.


Pero que sucede si no queremos guardar estos cuatro números en un vector String, y queremos hacerlo en variables con su respectivo tipo?, entonces trabajaríamos de la siguiente manera:

        

        Scanner entrada=new Scanner(System.in);
        int cantidad1=0;
        int cantidad2=0;
        String cantidad3="";//para guardar el número en notación científica.
        String cantidad4="";//el ultimo debe ser siempre String
   
    
 try 
 {

          entrada =
          new Scanner(new File( "ruta_a_miArchivo/miArchivo"))
          .useDelimiter("\\s*cantidad:\\s*");
   
   cantidad1=entrada.nextInt();
   
   cantidad2=entrada.nextInt();
   
   cantidad3=entrada.next(); //se espera número en notación científica.
   
   cantidad4=entrada.next();// el ultimo dato del archivo siempre se debe obtener como String
   
   entrada.close();

 } 
 catch (FileNotFoundException e)
 {
    e.printStackTrace();
 }
       
        System.out.println(cantidad1);  
        System.out.println(cantidad2);
        System.out.println(cantidad3);
        System.out.println(cantidad4);


En el código anterior cada vez que se ejecuta el método nextInt o next se avanza en la obtención de los datos y lógicamente estas instrucciones deben estar en el mismo orden a como llegan los datos que provienen del archivo;
Para el caso del ejemplo se obtienen primero dos números(con nextInt) pues son los primeros en llegar desde el archivo, luego un String (con next) y finalmente se espera otro número el cual se obtiene como un String por ser lo ultimo que se encuentra en el archivo y así evitar una excepción "InputMismatchException",
para remediar este ultimo detalle faltaría hacer una conversión después de la obtención u procurar que este ultimo dato siempre sea string.


Obtener datos desde una variable String

Igualmente a un objeto Scanner se le podría pasar una variable String en vez de un archivo:

                  

    Scanner entrada=new Scanner(System.in);

    float cantidad1=0.0f;

    int cantidad2=0;

    String cantidad3="";

    String cantidad4="";
    
    String texto="cantidad: 45,14 cantidad: 3262625 cantidad: 2x10^4 cantidad: cuatro ";//float con coma


       
    entrada = new Scanner(texto).useDelimiter("\\s*cantidad:\\s*");
   
   
   
    cantidad1=entrada.nextFloat();
   
    cantidad2=entrada.nextInt();
   
    cantidad3=entrada.next(); 
   
    cantidad4=entrada.next();
   
    entrada.close();
    
       
    System.out.println(cantidad1);  
    System.out.println(cantidad2);
    System.out.println(cantidad3);
    System.out.println(cantidad4);




Especificar una base para un número dado

Otra utilidad interenzante tiene que ver con los números, algunos métodos aceptan un parámetro numérico correspondiente a la base con la que se quiere manejar un número y de cierta manera no estar siempre con los decimales, ejemplo:

  Scanner entrada=new Scanner(System.in);    
  
  
System.out.print("Ingrese un octal: ");
 
//se espera un número en base 8 es decir caracteres del 0 al 7  
int numero = entrada.nextInt(8); 

System.out.println("el número octal ingresado, en decimal es: "+numero);
   
 

  
System.out.print("Ingrese un hexadecimal: ");
      
//se espera un número en base 16 es decir caracteres del 0 al 9 y/o A a la F
numero = entrada.nextInt(16); 

System.out.println("el número hexadecimal ingresado, en decimal es: "+numero);
   
 


  
System.out.print("Ingrese un binario: ");
       
//se espera un número en base 2 es decir solo caracteres 0 y 1
numero = entrada.nextInt(2); 

System.out.println("el número binario ingresado, en decimal es: "+numero);




En código anterior se aprecia la forma como se especifica la base, y la inmediata conversión que se hace automáticamente a decimal después de recibir el número por teclado.
si se ingresan caracteres que no corresponden a los caracteres de la base que se espera, entonces se producirá una excepción "InputMismatchException".

mas información: API Scanner Java 7

3 comentarios:

  1. Muchas gracias, esto estaba buscando, y el enlace ¡Excelente! Muy agradecido.

    Dios le bendiga.

    ResponderEliminar
  2. My bueno, me ha ayuidado a recordar! :)

    ResponderEliminar
  3. El Yucateco Casino & Hotel - Mapyro
    El Yucateco Resort and Casino is a 4-star hotel located just north of El Yucateco. The property 순천 출장샵 is set 원주 출장안마 on a cliff 오산 출장샵 overlooking the valley 문경 출장안마 of 나주 출장샵 Yucateco and

    ResponderEliminar