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");
        }
}


domingo, 28 de junio de 2015

Interfaces

COMPARABLE y SORT (ArrayList)

La implementación de esta interface permite realizar comparaciones entre elementos de un ArrayList o de vectores.
Su sintaxis es:
public class Clase implements Comparable<Clase>

De forma predeterminada, el método de esta interfaz, realiza comparaciones de acuerdo al primer atributo que encuentra en el objeto. Para personalizar la comparación basta con sobreescribir el método compareTo.

Una de las aplicaciones donde toma importancia esta interfaz es cuando se desea obtener una lista ordenada de acuerdo a un determinado criterio, para lo cual basta con agregar la siguiente línea de código:
Collections.sort(lista_a_ordenar);

Así por ejemplo:

Crearé 3 clases: Estudiante, Curso y Aplicación:

En la clase Estudiante:

public class Estudiante {

    private String numeroUnico;
    private String nombre;
    private Calendar fechaNacimiento;
    private Double ira;

    public Estudiante() {
        this.numeroUnico = null;
        this.nombre = null;
        this.fechaNacimiento = null;
        this.ira = 0.0;
    }

    public Estudiante(String numeroUnico, String nombre, Calendar fechaNacimiento, Double ira) {
        this.numeroUnico = numeroUnico;
        this.nombre = nombre;
        this.fechaNacimiento = fechaNacimiento;
        this.ira = ira;
    }

    public String getNumeroUnico() {
        return numeroUnico;
    }

    public void setNumeroUnico(String numeroUnico) {
        this.numeroUnico = numeroUnico;
    }

    public String getNombre() {
        return nombre;
    }

    public void setNombre(String nombre) {
        this.nombre = nombre;
    }

    public Calendar getFechaNacimiento() {
        return fechaNacimiento;
    }

    public void setFechaNacimiento(Calendar fechaNacimiento) {
        this.fechaNacimiento = fechaNacimiento;
    }

    public Double getIra() {
        return ira;
    }

    public void setIra(Double ira) {
        this.ira = ira;
    }

    public Integer obtenerEdad(Calendar fechaNacimiento) {
        Calendar fechaActual = Calendar.getInstance();
        Integer edad = fechaActual.get(Calendar.YEAR) - fechaNacimiento.get(Calendar.YEAR);
        if (fechaActual.get(Calendar.MONTH) < fechaNacimiento.get(Calendar.MONTH)){
            edad = edad-1;
        }
        return edad;
    }

    public Integer calcularMeses(Calendar fechaNacimiento) {
        Integer meses = 0;
        Calendar fechaActual = Calendar.getInstance();
        if (fechaActual.get(Calendar.MONTH) > fechaNacimiento.get(Calendar.MONTH)) {
            meses = fechaActual.get(Calendar.MONTH) - fechaNacimiento.get(Calendar.MONTH);
        } else {
            meses = fechaActual.get(Calendar.MONTH)- fechaNacimiento.get(Calendar.MONTH) + 12;
        }
        return meses;
    }

    @Override
    public String toString() {
        return String.format("\t%s\t%s\t\t%s años, %s mes(es)\t%.2f", this.numeroUnico, this.nombre, obtenerEdad(this.fechaNacimiento), calcularMeses(this.fechaNacimiento), this.ira);
    }
}

En la clase Curso:
public class Curso {
    
    private ArrayList<Estudiante> listaEstudiantes = new ArrayList<Estudiante>();
    
    public ArrayList<Estudiante> getListaEstudiantes() {
        return listaEstudiantes;
    }
    
    public void setListaEstudiantes(ArrayList<Estudiante> listaEstudiantes) {
        this.listaEstudiantes = listaEstudiantes;
    }
    
    public void agregarEstudiante(Estudiante nuevoEstudiante) {
        listaEstudiantes.add(nuevoEstudiante);
    }
    
    public void imprimirLista() {
        System.out.println("***************************ESTUDIANTES***************************");
        System.out.printf("\tNúmero único\tNombre\t\tEdad\t\t\tIRA\n");
        for (Estudiante e : listaEstudiantes) {
            System.out.println(e);
        }
    }
}

En la clase Aplicación:
public class Aplicacion {

    public static void main(String args[]) throws ParseException {
        Curso cr = new Curso();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        Calendar f1 = Calendar.getInstance();
        f1.setTime(sdf.parse("25-05-1993"));
        Estudiante e1 = new Estudiante("201210080", "Emily", f1, 29.3);
        cr.agregarEstudiante(e1);
        Calendar f2 = Calendar.getInstance();
        f2.setTime(sdf.parse("15-12-1991"));
        Estudiante e2 = new Estudiante("201210180", "Edison", f2, 39.1);
        cr.agregarEstudiante(e2);
        Calendar f3 = Calendar.getInstance();
        f3.setTime(sdf.parse("15-07-1994"));
        Estudiante e3 = new Estudiante("201010080", "Jenny", f3, 40.0);
        cr.agregarEstudiante(e3);
        cr.imprimirLista();
    }
}



Para comparar edades:

Primero se debe implementar la interfaz Comparable: y sobreescribir el método CompareTo:

public class Estudiante implements Comparable<Estudiante> {

@Override
    public int compareTo(Estudiante e) {
        int mayor = 0;
        if (obtenerEdad(this.fechaNacimiento) < e.obtenerEdad(e.getFechaNacimiento())) {
            mayor = -1;
        } else if (obtenerEdad(this.fechaNacimiento) > e.obtenerEdad(e.getFechaNacimiento())) {
            mayor = 1;
        } else {
            if (calcularMeses(this.fechaNacimiento) > e.calcularMeses(fechaNacimiento)) {
                mayor = -1;
            } else if (calcularMeses(this.fechaNacimiento) < e.calcularMeses(fechaNacimiento)) {
                mayor = 1;
            }
        }
        return mayor;
    }
}

Luego crear el método para ordenar la lista en la clase Curso:
 public void ordenar() {
        Collections.sort(listaEstudiantes);
    }

Finalmente, en la clase Aplicacion llamar a los métodos para ordenar e imprimir la lista:

cr.ordenar();
cr.imprimirLista();

El resultado de la ejecución es:



Si se desea ordenar por IRA, hay que sobreescribir el método CompareTo, así:
  
@Override
    public int compareTo(Estudiante e) {
        int mayor = 0;
        if (this.ira < e.getIra()) {
            mayor = -1;
        } else if (this.ira > e.getIra()) {
            mayor = 1;
        }
        return mayor;

    }

El resultado ahora será:

Finalmente para ordenar por Nombre, la sobreescritura del CompareTo es:

@Override
    public int compareTo(Estudiante e) {
        return this.nombre.compareTo(e.getNombre());
    }

Al ejecutar se obtendrá:



CLONEABLE

En ocasiones es necesario realizar una copia del contenido de cada campo de un objeto y sería erróneo realizarlo mediante asignación pues se tendrían dos objetos apuntando a una misma dirección de memoria lo que se vería repercutido en que si se cambiara posteriormente el valor de uno se verá también afectado en el otro objeto, para solucionar este inconveniente se puede implementar la interfaz cloneable de java y usar el método clone() para realizar el duplicado de un objeto. Por ejemplo:

Ahora sólo usaré dos clases, la clase Estudiante y la clase Aplicación; en la clase Estudiante se implementará la interfaz Cloneable y se sobreescribirá el método clone(), los atrributos, constructores, getters, setters, toString() y los métodos para calcular la edad serán los mismos usados en el ejemplo anterior, el método clone() tendrá el siguiente código:

public class Estudiante implements Cloneable{
    ...
    ...
    ...

    @Override
    public Estudiante clone(){
        Estudiante estClonado = new Estudiante(this.numeroUnico, this.nombre, this.fechaNacimiento, this.ira);
        return estClonado;
    }
}

Como ya no se usará la clase Curso, entonces en la clase Aplicacion se tendrá el siguiente código:

public static void main(String args[]) throws ParseException {
        ArrayList<Estudiante> listaEstudiantes = new ArrayList<Estudiante>();
        SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");
        Calendar f1 = Calendar.getInstance();
        f1.setTime(sdf.parse("25-05-1993"));
        Estudiante e1 = new Estudiante("201210080", "Emily", f1, 29.3);
        listaEstudiantes.add(e1);
        Calendar f2 = Calendar.getInstance();
        f2.setTime(sdf.parse("15-12-1991"));
        Estudiante e2 = new Estudiante("201210180", "Edison", f2, 39.1);
        listaEstudiantes.add(e2);
        Calendar f3 = Calendar.getInstance();
        f3.setTime(sdf.parse("15-07-1994"));
        Estudiante e3 = new Estudiante("201010080", "Jenny", f3, 40.0);
        listaEstudiantes.add(e3);
        System.out.println("***************************ESTUDIANTES***************************");
        System.out.printf("\tNúmero único\tNombre\t\tEdad\t\t\tIRA\n");
        for (Estudiante e : listaEstudiantes) {
            System.out.println(e);
        }
        System.out.println("");
        System.out.println("");
        listaEstudiantes.add(e1.clone()); //Se clona el objeto 1 y se agrega a la lista
        listaEstudiantes.add(e3.clone()); //Se clona el objeto 2 y se agrega a la lista
        System.out.println("***************************ESTUDIANTES***************************");
        System.out.printf("\tNúmero único\tNombre\t\tEdad\t\t\tIRA\n");
        for (Estudiante e : listaEstudiantes) {
            System.out.println(e);
        }
//Cambiamos los valores para comprobar que los objetos clonados no sufrirán ningún cambio
        e1.setNombre("Alex");
        e3.setIra(100.45);
        System.out.println("***************************ESTUDIANTES***************************");
        System.out.printf("\tNúmero único\tNombre\t\tEdad\t\t\tIRA\n");
        for (Estudiante e : listaEstudiantes) {
            System.out.println(e);
        }
    }

El resultado de la ejecución es: 


Los objetos clonados no sufrieron cambios.




:

martes, 7 de abril de 2015

Compilar un programa en java desde cmd y/o terminal

MANUAL DE USUARIO

¿CÓMO COMPILAR UN PROGRAMA EN JAVA?

Lo primero que se debe tener instalado para poder compilar un programa en Java es el JDK (Java Development Kit), el cual se puede descargar de la página oficial de oracle en el siguiente enlace: JDK 7. Una vez descargado, al ejecutar el instalador se debe únicamente dar clic en Next (siguiente) en las pantallas:








Posteriormente es necesario agregar java a la variable de entorno Path, para ello, al dar clic derecho en Equipo, luego en Configuración avanzada del sistema (panel derecho), Variables de entorno; buscar Path en Variables del sistema se obtendrá:

se procede a editar esta variable:

agregar la dirección donde se acaba de instalar java, sin borrar las existentes y separando la dirección añadida únicamente con un punto y coma (;). La dirección a añadir se la puede copiar fácilmente desde Equipo, así:



Finalmente, hay que dar clic en aceptar para guardar el cambio.

Abrir el cmd (símbolo del sistema de windows), y escribir javac, aparecerá lo siguiente:
lo que indica que se ha instalado correctamente. 


USANDO EL SÍMBOLO DEL SISTEMA DE WINDOWS

Para compilar un programa en java, se puede hacer uso del Bloc de notas para dar las instrucciones de lo que hará el programa.

En esta ocasión he hecho un programa bastante sencillo que únicamente muestre mi nombre. Las instrucciones que usé son:

Se debe guardar este archivo con el mismo nombre que se ubicó luego de class (en este caso Manual) y también poniendo la extensión (.java). Como se puede observar el nombre de mi archivo es Manual.java

Luego, en el cmd es necesario ubicarse en la ruta donde se guardó el archivo, en mi caso, guardé el archivo en el escritorio. En dicha ubicación se debe escribir javac Nombredelarchivo.java (en mi caso javac Manual.java) lo que creará un archivo class que usará el programa para la compilación.


Finalmente, para compilar el programa, en la misma ruta, basta poner java NombredelArchivo (en el caso del ejemplo java Manual), y se compilará el programa:



Bibliografía: Blog 1Blog 2Video 1Video 2


USANDO EL BASH DE LINUX

El JDK en linux se instala a través del terminal, con la instrucción:

sudo apt-get install openjdk-7-jdk


En linux, el editor que se usa es gedit; al igual que en bloc de notas es necesario guardar el archivo con la extensión .java para que las palabras reservadas se pongan de colores especiales, quedando así:

Una vez guardado, en el terminal, ingresamos la ruta donde se encuentra guardado el archivo, una vez ahí, se debe ingresar la instrucción javac Nombredelarchivo.java (en mi caso javac Manual.java) lo que creará un archivo tipo class, y posteriormente, si no hay errores, para ejecutar el programa la instrucción es java Nombredelarchivo (en el ejemplo java Manual).



Bibliografía: Blog 1, Blog 2, Blog 3.