miércoles, 1 de julio de 2015

I/O Stream

Hasta el momento para leer y escribir los datos durante la ejecución del programa se ha utilizado el teclado y la pantalla respectivamente para lograrlo; sin embargo, también se pueden usar archivos o crear archivos con la información requerida por el programa.

Para que una clase pueda hacer uso de los métodos para usar o crear un archivo es necesario que implemente la interfaz Serializable.

Los archivos pueden ser leídos o creados usando flujo de bytes o flujo de caracteres.
En la siguiente tabla se ilustran los tipos de objetos que se usarán dependiendo del tipo de flujo usado:

FLUJOS BASADOS EN BYTES
Para leer un archivo se usará la clase FileInputStream con la siguiente sintáxis:
FileInputStream nombreObjeto = new FileInputStream("nombreArchivo.txt");

Los métodos que se usarán son:

read() : lee un byte de los datos del archivo nombreArchivo.txt
close() : cierra el archivo y los recursos asociados a el.

Para escribir en un archivo se usará la clase FileOutputStreamsu sintáxis es:


FileOutputStream nombreObjeto = new FileOutputStream("nombreArchivo.txt");


Los métodos que se usarán son:

write(byte[] b): escribe  b.length bytes del array al archivo.
write(int b): escribe el byte b en el archivo.



Para obtener los resultados esperados, es necesario usar  un constructor que permite vincular los datos del archivo con otro objeto; este constructor es ObjectOutputStream.

Por lo tanto, ahora se escribirá en el archivo a través del objeto creado por este constructor. El método a usar es writeObject().
Así mismo, para leer el archivo, se usará el constructor ObjectInputStream y el método
readObject().
En el siguiente ejemplo se podrán visualizar las excepciones principales que se deben tratar al momento de trabajar con escritura de archivos:
public static void main(String args[]){

        ArrayList<Estudiante> listaEstudiantes = new ArrayList<Estudiante>();

        listaEStudiantes.add(new Estudiante("Alejandro", "1734242523"));
        listaEStudiantes.add(new Estudiante("Luis", "1732452354"));
 //Estableciendo objetos para manipular datos de archivos
        FileInputStream ingreso = null;
        FileOutputStream salida;

        try {
//Creación de archivo estudianteO.txt y lectura de archivo estudianteI.txt
ingreso = new FileInputStream("estudianteI.txt"); salida = new FileOutputStream("estudianteO.txt"); int c;

//Creación de Objetos para usar archivo
ObjectOutputStream salida = new ObjectOutputStream(inng); salida.writeObject(listaEstudiantes); //Ingresando listaEstudiantes al archivo estudianteO.txt salida.close(); //Cerrando el flujo, cerrando el archivo } catch (FileNotFoundException ex) { System.out.println("Archivo no encontrado"); } catch (ClassNotFoundException ex) {
            System.out.println("Clase vinculada al archivo no encontrada");
catch (IOException ex) {
            System.out.println("Ingreso erróneo de datos");
        }finally {
            if (ingreso != null) {
                ingreso.close();
            }
        }
    }
}

Excepciones

En la programación existen varios tipos de errores que pueden darse en tiempo de ejecución, de compilación o de codificación.

Un error en tiempo de ejecución puede deberse a varias razones, una de ellas es por ejemplo cuando se requiere el ingreso de números y el usuario ingresa caracteres, lo que produce un cierre prematuro y atropellado de la aplicación que suele ser bastante molesto; por esta razón, en java es posible manejar excepciones que eviten un cierre abrupto del programa en ejecución en caso de un error.

MANEJO DE EXCEPCIONES

Durante la codificación, es importante que el programador ejecute la aplicación imaginando que es un usuario totalmente inexperto en el manejo de la aplicación, sólo así el programador logrará identificar la mayoría si no todas las posibles causas que pueden provocar que la ejecución del programa termine sin éxito.

La sintaxis para tratar una excepción es:

try{
....
sentencias
....
}catch(TipoExcepcion nombreExcepcion){ 
...
instrucciones
...
}finally{
...
sentencias
...}

El bloque catch atrapa el error que podría aparecer eventualmente durante la ejecución de las sentencias dentro del bloque try. Finally, encierra instrucciones que se ejecutarán siempre, se produzca o no el error.

Para identificar la parte del código en la que se podría producir la excepción se usa la palabra reservada throws que permite lanzar la excepción:

static void nombreExcepcion(TipoArgumentos argumentos)throws TipoExcepcion{
throw new TipoExcepcion("mensaje");
}


EJEMPLO DE EXCEPCIONES COMUNES A TENER EN CUENTA:

  • DIVISIÓN PARA CERO:
public static void main(String args[]) {
        BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
        try {
            System.out.printf("Ingrese el numerador: ");
            Integer numero1 = Integer.parseInt(entrada.readLine());
            System.out.printf("Ingrese el denominador: ");
            Integer numero2 = Integer.parseInt(entrada.readLine());
            System.out.println("Los números ingresados son: " + numero1 + " y " + numero2);
            System.out.println("El resultado de la división es: " + numero1 / numero2);
        } catch (ArithmeticException e) {
            System.out.println("No se puede dividir para cero!");
        } finally {
            System.out.printf("Esto siempre se ejecuta\nAdiós\n");
        }
    }
  • INGRESO ERRÓNEO DE TIPO DE DATOS: Por ejemplo, se pide ingresar números pero el usuario ingresa caracteres:
public static void main(String args[]) throws IOException {
        BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
        try {
            System.out.printf("Ingrese el numerador: ");
            Integer numero1 = Integer.parseInt(entrada.readLine());
            System.out.printf("Ingrese el denominador: ");
            Integer numero2 = Integer.parseInt(entrada.readLine());
            System.out.println("Los números ingresados son: " + numero1 + " y " + numero2);
            System.out.println("El resultado de la división es: " + numero1 / numero2);
            } catch (NumberFormatException e) {
            System.out.println("Debes ingresar únicamente números!");
            e.printStackTrace(); //Imprime la información de la excepción
        } finally {
            System.out.printf("Esto siempre se ejecuta\nAdiós\n");
        }
    }

  • Si no se necesita imprimir un mensaje personalizado acerca del error producido, entonces se puede usar la siguiente instrucción:
public static void main(String args[]) throws IOException {
        BufferedReader entrada = new BufferedReader(new InputStreamReader(System.in));
        System.out.printf("Ingrese la edad: ");
        try {
            Integer edad = Integer.parseInt(entrada.readLine());
            System.out.println("La edad ingresada es: " + edad);
            } catch (IOException ex) {
            Logger.getLogger(Aplicacion.class.getName()).log(Level.SEVERE, null, ex);
        }
 }

CREACIÓN DE EXCEPCIONES


Si el programador necesita lanzar una excepción que no está dentro del lenguaje java, entonces puede crear tantas excepciones como crea necesarias, para lograrlo primero deberá crear una clase con el nombre de la excepción a ser lanzada, dicha clase deberá heredar de la clase Exception, en esta clase deberán ir las siguientes instrucciones:

public class NombreExcepcion extends Exception {
    public NombreExcepcion(String mensaje) {
        super(mensaje);
    }
}

Para poder usar la excepción, se debe hacer uso de la palabra throws en la sentencia donde se podría producir la excepción:

throw new NombreExcepcion("mensaje para mostrar");

Así por ejemplo:

Si se solicita el ingreso del intervalo de horas que se demorará una actividad, el primer valor deberá ser menor que el segundo:

public class RangoException extends Exception {

    public RangoException(String mensaje) {
        super(mensaje);
    }
}

public void main(String args[]) throws RangoException {
        if (horaMin > horaMax) {
            throw new RangoException("Rango ingresado incorrecto");
        }
}