lunes, 29 de abril de 2013

Lectura desde archivos secuenciales.

En esta ocasión nos proponemos utilizar el archivo creado en el post anterior para escribir un código que abra el archivo y recupere todos los objetos tipo Persona ahi almacenados.
Para ello abrimos el proyecto que estamos desarrollando y en el mismo paquete persistencia crearemos una clase que servirá para tener un punto de partida limpio. Le asignaremos el nombre LeerArchivo y configuraremos nuestro proyecto para que utilice esta nueva clase como clase de inicio.
Para lograr esto último debemos declarar un metodo público estático y que no devuelva resultado alguno llamado main.
La ventana de Netbeans parecería algo así:

Ajustamos las propiedades del proyecto para que la clase de inicio sea LeerArchivo.

Como primer paso vamos a verificar la existencia de nuestro archivo. Para ello utilizamos la clase File. Ya la sección import contiene la mayoría de las clases que se utilizaran.
Una vez hecho esto, nuevo metodo main contendrá el esquema siguiente. Nada nuevo hasta aquí.

Ahora vamos a utilizar un objeto de la clase Scanner que asociaremos esta vez al archivo en lugar a como se acostumbra System.in. Y leeremos el contenido del archivo línea a línea.

La instanciación e inicializacion de el objeto Scanner deben tambien incluirse dentro de un bloque try...catch. La primera línea es recuperada en la cadena line.
Ahora bien, no queremos solo la primera linea, queremos todas las que existan en el archivo origen. Debemos leer dentro de un ciclo. Modificaremos el código de esta forma.

Ahora que estamos leyendo una tras otra las lineas de codigo lo que estamos obteniendo en la cadena line cada vez es una linea de texto que contiene el numero de cuenta, el nombre completo y el teléfono separados por un caracter de tabulación.
Necesitamos algo que separe las cadenas segun un separador determinado. Eso que necesitamos es una clase de java.util. Se llama StringTokenizer.
A continuación se muestra el código que la usa:

 Como vemos la inicialización de los objetos de tipo StringTokenizer requieren una cadena a dividir en partes y otra subcadena que contiene el delimitador. Acto seguido se van obteniendo esas partes (tokens) y se van asignando a un objeto de tipo Persona. Observe que el numero de cuenta se recupera como una cadena que contiene uno o varios caracteres numéricos y por lo tanto hay que interpretarlo como byte antes de asignarselo al miembro correspondiente del objeto Persona. Las clases de envoltura para los tipos primitivos contienen una familia de metodos Parse que realizan esta operación. En nuestro caso se usa la clase de envoltura Byte y el metodo ParseByte.

Ahora solo queda el escribir el código que mostrará por consola el contenido desde el objeto Persona. Podría ser algo así el estado final del código:

Al ejecutar este proyecto. (Se debe haber establecido esta nueva clase como clase de arranque) la salida que muestra es la siguiente.


Podemos abrir y editar con el bloc de notas, el archivo que estamos cargando e interpretando en términos de una secuencia de objetos de tipo Persona. Por ejemplo se podría añadir una nueva linea que contenga un 4 separado por tabulación de un nombre y separado por tabulacion de un numero de telefono ficticio. Nuestro proyecto debe ser capaz de volver a leer el archivo y esta vez recuperar las cuatro personas.

Los archivos de subtitulos SRT son archivos simples de texto en los cuales se especifican el texto a mostrar, marca de tiempo a partir de la cual mostrarla y marca de tiempo para ocultarla. Estas simples tecnicas de manejo de archivos de texto pueden ser usadas para por ejemplo añadir a cada subtiulo una demora en segundos u otras variaciones.

Hasta aqui la parte correspondiente a la lectura de archivos secuenciales.





Escritura de datos en archivos de texto.

Esn esta ocasión se intentara usando la clase Persona y la declaracion del arreglo de la entrada anterior intentar guardar estos datos en un archivo de texto de acceso secuencial. Para ello se introducirá dos nuevas clases:
  1. File (java.io.File)
  2. Formatter (java.util.Formatter)

La figura siguiente muestra el punto de partida del código que se va a desarrollar.
































Ahora introduciremos la clase File,esta clase brinda informacion sobre archivos y carpetas. El tipo de informacion que brinda por ejemplo es: si existe o no, si es un archivo o es una carpeta y si es una carpeta cual es su contenido. En una palabra podemos acceder no al contenido del archivo sino a la informacion asociada al archivo.
Utilizaremos la clase file para comprobar si el archivo donde vamos a guardar el contenido del arreglo existe previamente. En caso de que exista haremos que la aplicación pregunte si desea sobreescribirlo.
El código podría tener el siguiente aspecto.



















Se declararó una cadena conteniendo la ruta completa al archivo donde se desea guardar la información. Acto seguido se declaro e inicializó una instancia de la clase File a la que se le dió el nombre de archivoDestino. Observe que se pasa como argumento la cadena que contiene el nombre y la ruta al fichero, al momento de inicializar la instancia de la clase File.
Se verifica la existencia previa del archivo usando el método exists() de el objeto archivoDestino y en caso de que retorne true pues se le pregunta al usuario de la aplicación si desea sobreescribirlo.
La variable de tipo boolean que se llama luzVerde  tendrá valor true si y solo si el primer caracter leido desde el teclado es una 'n' mayúscula o minúscula. si tal es el caso la aplicación asume que no se desea escibir en el fichero por lo que el código que se escribirá a continuacion no se ejecutará.
Si luzVerde es true entonces significa que tenemos "luz verde" para destruir el contenido previo del archivo sustituyendolo por nuevo contenido. lo cual haremos de la siguiente forma:

Declararemos e instanciaremos un objeto de tipo java.util.Formatter. Estará asociado al objeto archivoDestino y utilizaremos el metodo format de este nuevo objeto para escribir en el archivo. Cuando se termina la operacion de escritura,cerramos el archivo.
El código podría ser el siguiente:



El código que escribe en el archivo debe estar dentro de una estructura try...catch. Pues la instanciación y posterior llamada al metodo format del objeto formatter es suceptible a lanzr errores en tiempo de ejecución. La sección catch en este caso solo saca por consola el mensaje asociada a la excepción que se pueda producir.
La llamada a format se parece a printf de System.out excepto que el cambio de línea se logra mediante el metacaracter '%n' en lugar de '\n'.

Al ejecutar este código se obtendria la siguiente salida:












Si cambiamos el valor del nombre del archivo a algo como esto:
String fqNombreArchivo = "C:\\Users\\william\\Desktop\\ternaArbitral.txt";

Ahora obtendríamos al ejecutar:
Lo cual es correcto. Si lo volvemos a ejecutar, entonces la salida sería:


Inspeccionando el contenido de archivo creado deberiamos estar viendo algo como esto.

A modo de conclusion podemos ver que la escritura de archivos de texto se puede llevar a cabo facilmente usando la clase java.util.Formatter, particularmente llamando a su metodo format. La verificación de existencia de archivos puede llevarse a cabo usando la clase File.
Le propongo mejore el codigo anterior verificando no solo que si el archivo de salida ya existe si no que use el metodo isFile() de la clase File para verificar que es un fichero en lugar de una carpeta.

En el proximo post se utilizará la clase Scanner para leer el archivo que se creó en esta sesión y lo convierta nuevamente en un arreglo de objetos de tipo Persona.

Creacion de clases simples.

Usando NetBeans podemos crea nuevas tipos de datos abstractos (clases) usando el menu añadir clase al paquete que deseemos. Los paquetes sirven para agrupar clases relacionadas.
Por ejemplo, si lo que queremos es crear una clase llamada Persona con tres miembros públicos que podrian ser número de cuenta, nombre completo y telefono podriamos partir de crear un paquete al que llamaremos CustomClasses y añadir la clase a este paquete usando el comando correspondiente en el menu y obtendriamos al final lo siguiente:
Netbeans al proporcionar la nueva clase Persona.
Ahora se le añadirá la capacidad de almacenar la información requerida. Para esto usaremos miembros públicos. No es la técnica recomendable. Cambiaremos esto mas adelante en otro post donde se trate la creación de clases con java con un poco mas de profundidad.
Añadir los miembros se puede hacer declarando las variables dentro de del cuerpo de la clase usando el modificador de alcance public. Si no usamos public, los miembros no seran accesibles desde otras clases. Al terminar nuestro código tiene la apariencia siguiente:

 Ahora si editamos el archivo Persistencia.java podremos utilizar nuestro nuevo tipo de dato abstracto declarado. Para ello primero importamos la clases usando la sentencia import y el nombre de la clase, incluyendo el nombre del paquete que la contiene.

Acto seguido podemos instanciar la clase usando la sentencia:
Persona p = new Persona();

En la cual estamos estableciendo que la variable p es de tipo Persona y que la inicialice. Más adelante veremos en detalle metodos y constructores.

Depues de creada la instancia p de tipo Persona podemos asignarle valores a los miembros públicos ya declarados y tambien obtenerlos para por ejemplo mostrarlos por la consola. El codigo quedaría así.


El tipo de dato creado Persona puede ser usando tambien para declarar arreglos. El código sería el siguiente para declarar e inicializar un arreglo de tres personas.
 Con esto termina esta parte introductoria a la declaracion de clases usando Java.