0 valutazioniIl 0% ha trovato utile questo documento (0 voti)
53 visualizzazioni36 pagine
Guardar Archivos en Java, por la clase de RamdomAccessFile,Esta es la forma 'complicada' para almacenar información de nuestros programas en un archivo. Existe un método mucho más sencillo e incluso más fácil de aprender y comprender: La Serialización de Objetos. Si deseas almacenar datos de manera mucho más simple mejor revisa antes el capítulo de serialización.
Guardar Archivos en Java, por la clase de RamdomAccessFile,Esta es la forma 'complicada' para almacenar información de nuestros programas en un archivo. Existe un método mucho más sencillo e incluso más fácil de aprender y comprender: La Serialización de Objetos. Si deseas almacenar datos de manera mucho más simple mejor revisa antes el capítulo de serialización.
Guardar Archivos en Java, por la clase de RamdomAccessFile,Esta es la forma 'complicada' para almacenar información de nuestros programas en un archivo. Existe un método mucho más sencillo e incluso más fácil de aprender y comprender: La Serialización de Objetos. Si deseas almacenar datos de manera mucho más simple mejor revisa antes el capítulo de serialización.
Nota importante: Esta es la forma 'complicada' para almacenar informacin de nuestros
programas en un archivo. Existe un mtodo mucho ms sencillo e incluso ms fcil de aprender y comprender: La Serializacin de Objetos. Si deseas almacenar datos de manera mucho ms simple mejor revisa antes el captulo de serialiacin. !os programas creados hasta ahora han sido interesantes" algunos han sido #tiles y otros ilustrativos e incluso algunos sin utilidad especfica alguna. !as applets son divertidas en la mayora de los casos" los programas independientes tienden a ser algo mucho ms serio en cuanto a su fin. $ veces es necesario %ue los programas tengan la capacidad guardar informacin a largo plao" las varia&les son muy #tiles para almacenar valores temporales pero &ajo ciertas circunstancias es mejor guardar esa informacin y recuperarla incluso si se cierra el programa. Es claro %ue los ejemplos so&ran: programas administrativos" &ases de datos" &i&liotecas de consulta" che%ueo de saldos etc. 'ealmente somos muy afortunados como principiantes por%ue aun%ue este tipo de aplicaciones suelen ser de un enfo%ue ms prctico" (serio( y (profesional( son posi&les para nosotros" en )lanet *ava todo es fcil+. Existen dos formas generales para leer y escri&ir archivos: secuencialmente y aleatoriamente. !os archivos de acceso secuencial escri&en y recuperan la informacin de manera lineal" o sea %ue este tipo de archivos reci&en los datos suponiendo %ue t# los estas ordenando de manera previa. En tal caso si deseas guardar informacin so&re clientes cada uno con su respectivo n#mero de cuenta entonces de&es introducir la informacin en orden para %ue se almacene tam&in en orden. !os archivos de acceso aleatorio te permiten almacenar o recuperar informacin en orden aleatorio" es decir %ue si deseas guardar cierta informacin en la cuenta ,- entonces puedes desplaarte li&remente a dicha cuenta y escri&ir so&re ella" no se re%uiere %ue ordenes los datos" #nicamente te u&icas en la posicin %ue deseas y lees o escri&es informacin a tu gusto. *ava est tan &ien dise.ado %ue es relativamente simple tra&ajar con archivos ya sean de acceso secuencial o aleatorio" por lo tanto a final de cuentas depende de ti elegir una opcin entre am&as. En mi muy particular y humilde opinin se me facilitan ms los archivos de acceso aleatorio por lo tanto sern los #nicos %ue mostrar a%u. Entendiendo los Archivos de Acceso Aleatorio Si eres estudiante entonces ser muy fcil %ue comprendas los archivos de acceso aleatorio. Seguramente alguna ve has utiliado un cuaderno cuadriculado" la cuadrcula tiene cierta cantidad de cuadros horiontalmente y cierta cantidad de cuadros verticalmente" a mi me encantan los cuadernos de cuadro chico por%ue permiten escri&ir ms informacin /y por%ue mi letra es pe%ue.a0. 1n archivo aleatorio es prcticamente igual a una de estas hojas cuadriculadas solo %ue en ve de almacenar apuntes almacena &ytes. !os tipos de datos &sicos de *ava /tales como: char" dou&le" int" long" &oolean0 y en general toda la informacin %ue pasa por una computadora se puede expresar en trminos de &ytes" ya sea una imagen" un sonido" un video" un documento" etc. etc. todo puede convertirse a &ytes+ incluso nuestro cdigo gentico puede expresarse en &ytes /como lo demuestra el )royecto 2enoma 3umano0 por lo tanto si deseamos escri&ir informacin primero hay %ue convertirla a &ytes" en otros lenguajes de programacin dicha conversin se hace mano" en lenguajes como 4 y 455 la conversin es casi automtica y es ms fcil" en *ava es igual o a#n ms fcil. 'egresando a la explicacin" antes de escri&ir en una hoja /en un archivo0 sta de&e ser cuadriculada. En escritura a mano %ueda li&re la eleccin de escri&ir un n#mero o un texto" *ava necesita %ue seamos un po%uito ms claros so&re esto por%ue exige %ue antes de escri&ir indi%uemos claramente el tipo de dato %ue deseamos almacenar" esta eleccin es so&re los tipos de datos &sicos /es decir" de&es elegirlos entre: char" dou&le" int" long" &oolean0. 1na ve realiada la eleccin podemos proceder a (cuadricular( nuestro archivo y as marcar cuales cuadros sern para este tipo y cuales cuadros sern para este otro tipo y esto es todo" una ve marcados los cuadros ahora podemos escri&ir y leer li&remente" en *ava existe algo llamado puntero %ue es algo as como el lpi virtual %ue nos permite escri&ir la informacin" ste lapicito se puede desplaar a cual%uier posicin de nuestro archivo /de nuestra hoja cuadriculada0 y escri&ir el dato" ahh+ pero ese dato %ue intentes escri&ir de&e coincidir con el dato con el cual esta marcada la cuadricula en dicha posicin" por ejemplo si intentas escri&ir un int en una cuadricula %ue esta marcada como dou&le entonces se producir una excepcin %ue o&viamente no produce ning#n registro. $ grandes rasgos eso es todo" es muy fcil 6verdad7" ahora vamos a entrar en detalles explicando todo nuevamente con ms cuidado. Ejemplo en Pseudocdigo 8amos a ver el siguiente ejemplo en pseudocdigo: )ro&lema: 'ealiar un programa %ue permita almacenar los siguientes datos de un cliente: 9#mero" 9om&re" Sexo y Saldo. )asos de la solucin: 1. 4uadricular una hoja con : secciones: la primera almacenar un int /entero0 para el n#mero" la segunda un String /4adena de caracteres0 para el nom&re" la tercera un &oolean /true si es mujer" false si es hom&re0 para el sexo y la cuarta un dou&le /para el saldo %ue puede ser un n#mero decimal0. !o anterior significa %ue cada rengln de nuestra hojita ser de cuatro cuadros y digamos %ue ponemos ;<< renglones para almacenar los datos de ;<< futuros clientes. . 'eci&ir la informacin" supongamos %ue a cada cliente se le da la opcin de escoger su n#mero de cuenta as %ue si nuestro primer cliente nos da los siguientes datos: 9#mero: =- 9om&re: >scar 4hve Sexo: ?asculino Saldo: :,<.:, Entonces movemos nuestro lpi /puntero0 hasta la lnea =-" en dicha lnea hay : renglones /los de los tipos de datos0 y una ve all los escri&imos. 1na ve terminada la operacin de escritura en programacin formal sera &uena idea cerrar el archivo. !. >&tener la informacin almacenada" supongamos %ue ya tenemos muchos clientes y ahora deseamos realiar una consulta digamos del cliente -@. )ara esto primero movemos nuestro lapicito a la lnea -@ y una ve all leemos los datos escritos: 9#mero: -@ 9om&re: $gustn !ara Sexo: ?asculino Saldo: A@:.BC 9uevamente una ve terminada esta operacin de&emos cerrar el archivo. Dinalmente la modificacin y eliminacin de datos es similar" para modificar nos colocamos en la lnea correspondiente al n#mero de nuestro cliente y so&rescri&imos los datos. )ara eliminar nos moveramos a la lnea con el lapicito y en ve de &orrar /cosa %ue sera lo convencional con una hoja y lpi convencionales0 esta ve tenemos %ue escri&ir datos vacos" por ejemplo: 9#mero: < 9om&re: ( ( Sexo: false Saldo: <.< !a cadena ( ( en *ava es una cadena vaca y si mal no recuerdo un false corresponde a un &olean recin creado" si se dan cuenta realmente no tendra mucho caso &orrar el n#mero por%ue de cual%uier manera ste ser el mismo si alg#n cliente lo elige /siempre se encontrar en la misma lnea0" a#n as lo &orr por consistencia. )ues &ien" ese fue el ejemplo. $hora veamos una clase %ue nos servir para (cuadricular( nuestro archivo. 4uando se escri&en los datos sean del tipo %ue sean en un archivo aleatorio estos de&en ser convertidos a su contraparte en &ytes" lo %ue implica %ue si tu a&res alg#n archivo aleatorio con el Eloc de 9otas por decir algo" no vers los datos como los guardaste sino %ue los vers unos sm&olos medio raritos. 4uando creamos una cuadricula en realidad estamos marcando el archivo con &ytes %ue representan valores vacos /igual %ue al eliminar registro0" este marcado se realia de la siguiente manera /en &ase al ejemplo en pseudocdigo0:
"egistro 1 "egistro "egistro !.. 9#mero 9om&re Sexo Saldo 9#mero 9om&re Sexo Saldo 9#mero 9om&re Sexo Saldo F as sucesivamente hasta llegar al registro ;<<. $un%ue por motivos didcticos lo idealiamos de la siguiente manera: "egistro 1 9#mero 9om&re Sexo Saldo "egistro 9#mero 9om&re Sexo Saldo "egistro !... 9#mero 9om&re Sexo Saldo F as sucesivamente. 'ecuerden %ue pretendemos visualiar un archivo de acceso aleatorio como un grupo de registros" cada registro tiene : cuadros: un cuadro entero" uno de cadena" uno &olean y uno dou&le. )or eso es mejor idealiarlo como la segunda ta&la aun%ue el puntero /lapicito0 lo perci&e como la primera. La clase #ile !a clase Dile a diferencia de lo %ue indica su nom&re /Dile significa $rchivo0 no tiene como fin servir para leer o escri&ir archivos" se trata #nicamente de una herramienta para o&tener informacin acerca de los archivos. 6Gu tipo de informacin7 si es de solo lectura" si se puede modificar" su tama.o" su nom&re" su carpeta" la fecha de su #ltima modificacin" si es %ue existe" entre otros datos. Ham&in permite crear o &orrar archivos" pero como ya dije: no sirve para escri&ir o leer. Se supone %ue una aplicacin %ue pretende escri&ir en un archivo de&e crear tal archivo" si este archivo ya existe entonces no ser necesario crearlo" el ejemplo de $rchivos $leatorios mostrado en esta seccin recurre a la clase Dile para confirmar si el archivo %ue vamos a crear ya existe" si a#n no existe entonces se crea uno /marcando su cuadrcula de datos respectiva0 y si ya existe pues no se hace nada para dejarlo tal como esta" por%ue o&viamente deseamos conservar los datos almacenados+ lo %ue sucede es %ue los constructores de 'andom$ccessDile aun%ue pueden crear o a&rir un archivo existente no nos permiten marcar la cuadrcula de datos %ue deseamos. Si desean ms informacin acerca de la informacin %ue pueden o&tener mediante la clase Dile les aconsejo revisar detenidamente la *ava $)I /la clase Dile" o&viamente0. La clase "andomAccess#ile !a clase 'andom$ccessDile nos da las capacidades %ue &uscamos de lectura y escritura de archivos. El constructor %ue utiliaremos para este ejemplo es: pu&lic 'andom$ccessDile/String name" String mode0 donde (name( representa el nom&re del archivo y (mode( indica el modo en el cual a&riremos el archivo" am&os son cadenas. El nom&re es li&re de elegir si se trata de un archivo nuevo o de&e ser consultado en el caso de un archivo existente /el caso del ejemplo0" el nom&re se coloca con su extensin correspondiente. En cuanto al modo existen dos posi&ilidades: (rJ( o (r(" rJ indica lectura y escritura /read K Jrite0 mientras %ue r indica solo lectura /read0. Este constructor puede lanar diversas excepciones %ue en general se pueden atrapar como un 9ull)ointerException para exhi&irse en pantalla o para realiar alguna otra manipulacin cosa %ue jams he hecho puesto %ue yo tam&in sigo siendo principiante+. El siguiente listado muestra algunos mtodos de la clase 'andom$ccessDile: void close/0 4ierra el archivo de acceso aleatorio y li&era todos los recursos del sistema asociados con este archivo long getDile)ointer/0 'egresa la posicin actual del apuntador /lapicito0 long length/0 'egresa la longitud del archivo &oolean readEoolean/0 !ee un dato &olean de este archivo char read4har/0 !ee un caracter unicode de este archivo /una letra0 dou&le readLou&le/0 !ee un dou&le de ese archivo int readInt/0 !ee un entero de este archivo String read1HD/0 !ee una cadena de este archivo void seeM/long pos0 Dija el apuntador en la posicin (pos( partiendo del principio del archivo para colocarlo en donde se piensa leer o escri&ir void JriteEoolean/&oolean v0 Escri&e un valor &olean void Jrite4har/int v0 Escri&e un caracter void Jrite4hars/String s0 Escri&e una serie de caracteres void JriteLou&le/dou&le v0 Escri&e un dou&le void JriteInt/int v0 Escri&e un int void Jrite1HD/String str0 Escri&e una cadena >&viamente hay ms mtodos" consulten la *ava $)I para mayor informacin. $un%ue escri&iremos varias cadenas /String0 no vamos a utiliar ni Jrite1HD/0 o su contraparte read1HD/0" esto es por%ue a#n de&o estudiar mejor estos mtodos por%ue al parecer escri&en cadenas de tama.o ar&itrario lo %ue hara errtico el tama.o de nuestra cuadricula de datos" la verdad a#n no estoy seguro del todo por eso decid no arriesgarme" ya veremos ms adelante con una explicacin mucho ms detallada la tcnica %ue aprend de un li&ro para almacenar cadenas de una manera ms clara y predeci&le aun%ue si sa&es &ien el manejo de cadenas para archivos de acceso aleatorio y o&servas %ue mi cdigo puede ser ms simple acepto tus sugerencias. Ejemplo $ %n programa simple de administracin de cuentas para un gimnasio El siguiente ejemplo ilustra una posi&le forma de crear un programa sencillo /aun%ue ya puede ser muy #til0 de un administrador de cuentas para un gimnasio" el pro&lema es el siguiente: (4rear un programa %ue administre cuentas de clientes" cada registro de&e contener: 9#mero" 9om&re y )eso de la persona. Se de&en poder hacer altas" &ajas" consultas y modificaciones a las cuentas.( El programa se organia de la siguiente manera: >rganiacion del )rograma &lase 'escripcin clase cuenta'egistro 4rea y manipula el archivo de acceso aleatorio" contiene el orden preciso en %ue de&en escri&irse y leerse los datos" no tiene interfa grfica. clase alta 'ecurre a la clase cuenta'egistro para dar de alta una cuenta" hereda de un Drame con una interfa grfica para o&tener los datos desde campos de texto clase &aja 'ecurre a la clase cuenta'egistro para dar de &aja una cuenta" hereda de un Drame con una interfa grfica %ue o&tiene el n#mero de cuenta a eliminar clase consulta 'ecurre a la clase cuenta'egistro para leer una cuenta" hereda de un Drame con una interfa grfica para o&tener el n#mero de cuenta a consultar clase modificar 'ecurre a la clase cuenta'egistro para modificar una cuenta" hereda de un Drame con una interfa grfica para o&tener los datos desde campos de texto clase archivos$leatorios )rograma principal" a%u se encuentra el mtodo main %ue cargar este Drame principal" se recurre a la clase Dile para revisar si existe un archivo de datos" si no existe se crea uno /y su cuadricula de datos respectiva0 mediante la clase cuenta'egistro 4omo ven de hecho todas las clases excepto (cuenta'egistro( heredan de frame" la clase archivos$leatorios %ue es el Drame principal tendr : &otones para crear ya sea un (alta(" (&aja(" (consulta( o (modificar(" cada una de estas su&ventanas tendr sus &otones" la&els y campos de texto respectivos %ue se ordenan mediante un !ayout /acomodamiento0 de tipo 2rid!ayout con : lneas y B columnas. 'evisemos cada clase en detalle para comprender mejor todo. La clase (cuenta"egistro( Esta clase es el coran para manejar el archivo" contiene funciones para escri&ir o leer en l" adems tam&in permite manipular el apuntador /el lpi0 y cerrar el archivo entre otras cosas" veamos el cdigo y despus voy a explicar funcin por funcin: import java.io.NO pu&lic class cuenta'egistro P pu&lic final int sie Q ,BO 'andom$ccessDile archivoO pu&lic int numeroO pu&lic String nom&reO pu&lic dou&le pesoO RN 4onstructor de la clase de hecho #nicamente carga un archivo NR pu&lic cuenta'egistro/String nom&re" String modo0 P a&rir$rchivo/nom&re" modo0O S RN Duncin %ue se llama desde el constructor" a%u se llama al constructor de 'andom$ccessDile y se maneja la excepcin %ue podra lanar NR pu&lic void a&rir$rchivo/String nom&re" String modo0 P try P archivo Q neJ 'andom$ccessDile/nom&re" modo0O S catch /I>Exception e0 P System.err.println/(Error al a&rir el archivo ( 5 e.toString/00O System.exit/<0O S S RN Duncin %ue se llama para cerrar el archivo" tam&in se maneja la excepcin %ue podra lanar NR pu&lic void cerrar$rchivo/0 P try P archivo.close/0O S catch /I>Exception e0 P System.err.println/ (Error al cerrar el archivo ( 5 e.toString/0 0O System.exit/<0O S S RN Duncin %ue lee informacin desde el archivo" o&tiene los datos de las funciones respectivas a cada tipo de dato" tam&in maneja la excepcin si es %ue es lanada NR pu&lic void leer/0 P try P numero Q leerEntero/0O nom&re Q leer4adena/B<0O peso Q leerLou&le/0O S catch /I>Exception e0 P System.err.println/(Error al leer en el archivo: ( 5 e.toString/00O System.exit/<0O S S RN Duncin %ue escri&e directamente a un archivo llamando a las funciones respectivas para cada tipo de dato" tam&in maneja la excepcin si es %ue sta es lanada NR pu&lic void escri&ir/0 P try P escri&irEntero/numero0O escri&ir4adena/nom&re" B<0O escri&irLou&le/peso0O S catch /I>Exception e0 P System.err.println/(Error al escri&ir en el archivo: ( 5 e.toString/00O System.exit/<0O S S RN Duncin privada %ue escri&e un entero en el archivo prcticamente sta es #nicamente una traduccin al espa.ol por%ue realmente no cam&ia la original de ninguna manera NR private void escri&irEntero/int entero0 throJs I>Exception P archivo.JriteInt/entero0O S RN Duncin privada %ue lee un entero NR private int leerEntero/0 throJs I>Exception P return archivo.readInt/0O S RN Duncin privada %ue escri&e un dou&le NR private void escri&irLou&le/dou&le precision0 throJs I>Exception P archivo.JriteLou&le/precision0O S RN Duncin privada %ue lee un dou&le NR private dou&le leerLou&le/0 throJs I>Exception P return archivo.readLou&le/0O S RN Duncin privada %ue escri&e una cadena NR private void escri&ir4adena/String s" int num!etras0 throJs I>Exception P if/s QQ null0 s Q ( (O if /s.length/0 TQ num!etras0 P archivo.Jrite4hars/s0O for/int i Q s.length/0O i T num!etrasO 55i0 archivo.Jrite4har/' '0O S else P archivo.Jrite4hars/s.su&string/ <" num!etras00O S S RN Duncin privada %ue lee una cadena NR private String leer4adena/int num!etras0 throJs I>Exception P String s Q ((O for/int i Q <O i T num!etrasO 55i0 s 5Q archivo.read4har/0O return s.trim/0O S RN Duncin %ue mueve el puntero" esta funcin desplaa el puntero a la posicin n /en &ytes0 se maneja la excepcin si es %ue es lanada NR pu&lic void seeM/long n0 P try P archivo.seeM/n0O S catch /I>Exception e0 P System.out.println/(Error al mover el puntero de escritura a n &ytes ( 5 e.toString/00O S S S E)plicacin de la clase cuentas"egistro )rimero importamos el pa%uete java.io ya %ue la clase 'andom$ccessDile pertenece a dicho pa%uete: import java.io.NO Lespus tenemos las siguientes varia&les glo&ales:
pu&lic final int sie Q ,BO 'andom$ccessDile archivoO pu&lic int numeroO pu&lic String nom&reO pu&lic dou&le pesoO El 'andom$ccessDile nom&rado (archivo( es el encargado de a&rir y cargar el archivo como veremos en el constructor un poco ms adelante. !as varia&les p#&licas: numero" nom&re y peso servirn para almacenar los valores tomados desde los campos de texto de manera exterior ya %ue sta clase no posee interfa grfica" alguna otra clase de&er pasar los datos introducidos por el usuario a estas varia&les. En cuanto a la varia&le sie declarada como pu&lic final es un valor constante %ue sirve para especificar el tama.o de un registro /de una cuenta0 en &ytes. 'ecuerden %ue todos los datos o&tenidos de&en convertirse a &ytes" para determinar este tama.o necesitamos dos cosas: !os datos %ue almacenar cada cuenta y la siguiente ta&la: Hama.o de datos en &its y &ytes Hipo de datoHama.o en &its Hama.o en &ytes &oolean ; ; char ;C B int -B : long C: @ float -B : dou&le C: @ Nota* >cho &its corresponden a un solo y #nico &yte" /@&its Q ;&yte0. $hora vamos a aclarar un poco ms las cosas" seg#n el pro&lema tenemos %ue almacenar tres datos por cada registro: 1n n#mero /entero0 1n nom&re /cadena0 1n peso /numero dou&le0 Entonces" guardaremos un entero /int0" una cadena /String0 y un dou&le. Guede en %ue no i&a a utiliar los mtodos para guardar Strings por lo tanto voy a recurrir a la idea de %ue una cadena es un arreglo de caracteres" seg#n lo anterior tenemos definido el tama.o para el n#mero de cuenta %ue sera: + b,tes" tam&in tenemos definido el tama.o para el peso /es un dou&le0: - b,tes" solo falta definir el tama.o de la cadena" supongan %ue vamos a guardar unas B< letras %ue incluirn al nom&re junto con su apellido o sea %ue la cadena contendra por ejemplo: ('oxana 2ara ( %ue son B< caracteres" es importante notar %ue un espacio vaco tam&in es un caracter" es acepta&le por lo tanto dejaremos B< caracteres como tama.o de la cadena es decir: B<xB Q +. b,tes. Si hacemos la suma de todos los datos tenemos el resultado para el tama.o de un registro /una cuenta0: / b,tes totales. )ero... 6por %u de&emos o&tener este valor7 por%ue nuestro puntero o lapicito se mueve en &ytes" es decir nosotros le de&emos indicar exactamente el n#mero de &ytes %ue de&e moverse a partir del inicio del archivo antes de escri&ir. ?s adelante veremos %ue nuestro lapicito solo se mover en m#ltiplos de / b,tes tanto para leer como para escri&ir. El constructor es: RN 4onstructor de la clase de hecho #nicamente carga un archivo NR pu&lic cuenta'egistro/String nom&re" String modo0 P a&rir$rchivo/nom&re" modo0O S RN Duncin %ue se llama desde el constructor" a%u se llama al constructor de 'andom$ccessDile y se maneja la excepcin %ue podra lanar NR pu&lic void a&rir$rchivo/String nom&re" String modo0 P try P archivo Q neJ 'andom$ccessDile/nom&re" modo0O S catch /I>Exception e0 P System.err.println/(Error al a&rir el archivo ( 5 e.toString/00O System.exit/<0O S S !a segunda funcin a&rir$rcivo/0 a&re el documento con los datos %ue pasa el constructor" am&os: el constructor y la funcin a&rir$rchivo/0 estn relacionadas pero &ien pude ha&er puesto todo el contenido de la funcin en el constructor. Ham&in se atrapa una excepcin si es %ue sta se genera %ue indica un mensaje de error en la lnea de comandos mediante System.err.println/0. Lespus tenemos la funcin encargada de cerrar el archivo: RN Duncin %ue se llama para cerrar el archivo" tam&in se maneja la excepcin %ue podra lanar NR pu&lic void cerrar$rchivo/0 P try P archivo.close/0O S catch /I>Exception e0 P System.err.println/ (Error al cerrar el archivo ( 5 e.toString/0 0O System.exit/<0O S S Existen dos formas de sa&er %ue una funcin tal como archivo.close/0 lana una excepcin" la primera y ms fcil es consultando la *ava $)I" si el mtodo incluye la clusula throJs significa %ue puede lanar una excepcin del tipo marcado" la segunda es %ue el compilador te lo indi%ue por%ue no te permitir compilar hasta %ue atrapes la excepcin %ue se puede generar" el mensaje general sera algo as como: Exception java.io.I>Exception must &e caught" or it must &e declared in the throJs clause of this method /!a excepcion java.io.I>Exception de&e ser atrapada o de&e ser relanada desde ste mtodo con throJs0. En el caso anterior se atrapa en ve de relanarla aun%ue no hago gran cosa por manejarla ms %ue exhi&ir en pantalla %ue sucedi al cerrar el archivo. !a siguiente funcin es la encargada de escri&ir en el archivo: RN Duncin %ue lee informacin desde el archivo" o&tiene los datos de las funciones respectivas a cada tipo de dato" tam&in maneja la excepcin si es %ue es lanada NR pu&lic void leer/0 P try P numero Q leerEntero/0O nom&re Q leer4adena/B<0O peso Q leerLou&le/0O S catch /I>Exception e0 P System.err.println/(Error al leer en el archivo: ( 5 e.toString/00O System.exit/<0O S S Esta funcin llama a otras %ue veremos un poco ms a&ajo" todas las funciones de escritura y lectura pueden lanar excepciones de tipo I>Exception /excepcin de entrada y salida" aludiendo a la entrada o salida de datos desde cual%uier fuente0" por lo tanto estas de&en ser atrapadas en alg#n momento" a%u doy una solucin drstica a este pro&lema: salir del programa mediante System.exit/<0O lo cual indica %ue algo muy malo sucedi" puede ser %ue el archivo haya desaparecido de alguna forma /no me imagino como" pero puede suceder0. $lgo muy importante respecto al mtodo anterior y al siguiente es %ue am&os de&en realiar ya sea la escritura o la lectura bajo la misma secuencia" si los datos se escri&en en cierto orden los datos de&en leerse en ese mismo orden para recuperarlos apropiadamente por%ue sera imposi&le leer un entero en un cuadro marcado como dou&le por ejemplo" se producira un error+. Estos mtodos solo escri&en o leen el registro de una cuenta" desplaar el puntero para leer o escri&ir otras cuentas... es otra historia. RN Duncin %ue escri&e directamente a un archivo llamando a las funciones respectivas para cada tipo de dato" tam&in maneja la excepcin si es %ue sta es lanada NR pu&lic void escri&ir/0 P try P escri&irEntero/numero0O escri&ir4adena/nom&re" B<0O escri&irLou&le/peso0O S catch /I>Exception e0 P System.err.println/(Error al escri&ir en el archivo: ( 5 e.toString/00O System.exit/<0O S S !a funcin anterior de escritura tam&in recurre a funciones %ue veremos ms a&ajo" el manejo de la excepcin es similar al mtodo de lectura" tam&in toma la medida un poco drstica de salir del programa si se lana una excepcin" la I>Exception podra lanarse si el disco se llena o si el archivo es &lo%ueado de alguna manera. !a siguiente funcin se encarga de escri&ir un entero: RN Duncin privada %ue escri&e un entero en el archivo prcticamente sta es #nicamente una traduccin al espa.ol por%ue realmente no cam&ia la original de ninguna manera NR private void escri&irEntero/int entero0 throJs I>Exception P archivo.JriteInt/entero0O S 4reo %ue su descripcin es clara" en ve de manejar la excepcin %ue puede lanar el mtodo JriteInt/0 se ocupa mejor de relanarla a cual%uier mtodo %ue la llame de modo %ue l la maneje a su modo" en otras pala&ras el throJsI>Exception es como si ste mtodo advirtiera a cual%uier otra mtodo %ue intente usarlo: &ien" me puedes usar pero yo soy capa de lanar una excepcin de tipo I>Exception" te advierto para %ue t# la manejes o &ien para %ue la relances" tu decides. !os mtodos leer/0 y escri&ir/0 se encargan de manejar esa excepcin. !as siguientes funciones son muy similares a la anterior: RN Duncin privada %ue lee un entero NR private int leerEntero/0 throJs I>Exception P return archivo.readInt/0O S RN Duncin privada %ue escri&e un dou&le NR private void escri&irLou&le/dou&le precision0 throJs I>Exception P archivo.JriteLou&le/precision0O S RN Duncin privada %ue lee un dou&le NR private dou&le leerLou&le/0 throJs I>Exception P return archivo.readLou&le/0O S !o anterior es simple" a%u comiena lo interesante. 6'ecuerdan %ue no i&a a utiliar ninguno de los mtodos de 'andom$ccessDile para leer y escri&ir cadenas7 pues eso significa %ue de&o crear algo similar %ue lea y escri&a las dichosas cadenas" como una cadena es un arreglo de caracteres lo %ue hago para escri&ir la cadena es tomar los caracteres %ue contiene y despus utiliar la funcin Jrite4hars/0 para escri&irlos de manera individual: RN Duncin privada %ue escri&e una cadena NR private void escri&ir4adena/String s" int num!etras0 throJs I>Exception P if/s QQ null0 s Q ( (O if /s.length/0 TQ num!etras0 P archivo.Jrite4hars/s0O for/int i Q s.length/0O i T num!etrasO 55i0 archivo.Jrite4har/' '0O S else P archivo.Jrite4hars/s.su&string/ <" num!etras00O S S El primer (if( se encarga de checar %ue la cadena no est vaca y en caso de %ue lo est la llena con B< caracteres vacos /tal como ha&amos acordado este es el tama.o de una cadena por almacenar0" el segundo if revisa %ue el tama.o de la cadena no exceda a la varia&le entera (num!etras(" esta varia&le sirve para fijar precisamente el lmite %ue acordamos de B< caracteres" siempre se pasar tanto en este mtodo como el %ue lee una cadena /el siguiente0. Si esta condicin se cumple entonces se escri&en todos los caracteres %ue contenga la cadena mediante Jrite4hars/0" aun%ue tam&in si esta condicin es verdadera tam&in implica %ue la cadena posi&lemente es incluso menor %ue el re%uisito de B< caracteres entonces se ejecuta un ciclo for %ue llena los espacios restantes /%ue no ocupa la cadena0 con espacios vacos o caracteres vacos. Dinalmente el (else( implica %ue la cadena no cumpli la primera condicin" es decir %ue la cadena contiene ms de B< caracteres" lo %ue se hace a%u es inevita&lemente recortar la cadena y solo incluir los B< caracteres acordados" la funcin su&string/0 de la clase String recorta la cadena" su primer argumento es el ndice en el cual se inicia y el #ltimo indica el final del recorte dentro del arreglo" en otras pala&ras: este mtodo recorta todo lo %ue est fuera del ndice < de la cadena hasta el ndice B<. !a siguiente funcin se encarga de leer una cadena escrita: RN Duncin privada %ue lee una cadena NR private String leer4adena/int num!etras0 throJs I>Exception P String s Q ((O for/int i Q <O i T num!etrasO 55i0 s 5Q archivo.read4har/0O return s.trim/0O S Se supone %ue en este ejemplo siempre pasaremos un argumento de B< como (num!etras(" primero creamos una cadena nom&rada (s( para almacenar todos los caracteres /del ; al B<0" despus le asignamos un valor vaco: ((" el ciclo for se encarga de recorrer :< &ytes" convertirlos en caracteres e ir anexando cada lectura a la cadena. Dinalmente se regresa la cadena leda mediante: return s.trim/0O la funcin trim/0 se encarga de (acortar( la cadena eliminando los caracteres en &lanco /los espacios propiamente dichos0 %ue pudiera tener al final" los intermedios no se eliminan. 4omo esta es una lectura no importa si se eliminan los espacios en &lanco del final con tal de o&tener los caracteres %ue nos importan" en la escritura los espacios son ms importantes como ya vimos. Dinalmente tenemos otra funcin muy importante" la %ue desplaa nuestro puntero o lpi: RN Duncin %ue mueve el puntero" esta funcin desplaa el puntero a la posicin n /en &ytes0 se maneja la excepcin si es %ue es lanada NR pu&lic void seeM/long n0 P try P archivo.seeM/n0O S catch /I>Exception e0 P System.out.println/(Error al mover el puntero de escritura a n &ytes ( 5 e.toString/00O S S
El argumento (n( reci&e la cantidad de &ytes %ue nos desplaaremos desde el principio del archivo. Esta funcin solo se encarga de atrapar la excepcin para evitarnos tener %ue atraparla cada ve %ue la llamemos desde el exterior" es &astante #til mientras se colo%ue un mensaje correspondiente indicando exactamente %ue fue lo %ue sucedi si es %ue es lanada+. Hodos los System.out.println/0 reci&en una cadena como argumento" esta cadena generalmente exhi&e informacin. Este mensaje solo se muestra en la consola del sistema tal como la ventana de L>S" as %ue nunca se ver desde una interfa grfica. La clase (alta( Esta clase es mucho ms sencilla %ue la anterior" su propsito es mostrar un Drame con diversos componentes grficos los cuales incluyen campos de texto %ue o&tienen los datos para dar de alta una cuenta" es decir un registro de: un n#mero" un nom&re y un dou&le. $ estas alturas doy por hecho %ue ya conocen la creacin &sica de una interfa grfica sencilla tal como la %ue usaremos" lo mismo para las interfaces por%ue utiliaremos muchos $ction!isteners para manejar los eventos y UindoJ$dapters para cerrar los Drames. En s la #nica parte de cdigo relacionada con el alta de una cuenta es el %ue se encuentra dentro de la funcin action)erformed/0: import java.aJt.NO import java.aJt.event.NO pu&lic class alta extends Drame implements $ction!istener P !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton guardar4uenta Q neJ Eutton/(2uardar+(0O cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O pu&lic alta/0 P super/($lta de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/guardar4uenta0O guardar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ guardar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.nom&re Q Hnom&re.getHext/0O Lou&le p Q neJ Lou&le/Hpeso.getHext/00O archivo.peso Q p.dou&le8alue/0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( guardado exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S S E)plicacin de la clase (alta( )rimero importamos los pa%uetes %ue vamos a utiliar" heredamos de la clase Drame por%ue el siguiente cdigo crear una ventana con diversos componentes" implementamos la interfa $ction!istener para atrapar los eventos generados: import java.aJt.NO import java.aJt.event.NO pu&lic class alta extends Drame implements $ction!istener P $hora declaramos e inicialiamos al mismo tiempo diversos componentes tales como eti%uetas y campos de texto" el &otn nos permite guardar la informacin una ve capturada: !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton guardar4uenta Q neJ Eutton/(2uardar+(0O 4omo siguiente paso creamos un nuevo archivo &asndonos en la clase cuenta'egistro creada anteriormente" lo llamamos cuentas.dat y lo a&rimos en modo lecturaVescritura para poder escri&ir en l: cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O Lespus creamos el constructor" el super/0 llama al constructor de la superclase" es decir de la clase Drame y pasa una cadena como argumento %ue representa el ttulo de la ventana. Esta&lecemos un nuevo acomodamiento de componentes mediante set!ayout/0 %ue reci&e como argumento un nuevo 2rid!ayout %ue divide nuestra ventana en : lneas y B columnas" fijamos la ventana en la coordenada B<<" ;=< y le fijamos un ancho de B:< y un alto de ;-< /recuerda %ue estas coordenadas son en pixeles0. pu&lic alta/0 P super/($lta de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/guardar4uenta0O guardar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S 4omo siguiente paso agregamos uno a uno los componentes con add/0 en el orden correcto. Dinalmente agregamos el !istener /definido en esta misma clase" de ah %ue se pase un this0 %ue implementa nuestra clase al &otn nom&rado (guardar4uenta( y agregamos un UindoJ!istener a la ventana %ue esta definido como una clase interna o innerclass de esta misma clase tal como sigue: pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S 'ecuerden UindoJ$dapter es una clase a&stracta %ue hereda de UindoJ!istener %ue sirve para ahorrarnos el tener %ue definir todos los mtodos %ue esta interfa /UindoJ!istener0 exige" as solo definimos el mtodo %ue necesitamos en este momento para cerrar la ventana: JindoJ4losing/0. )or #ltimo viene la parte ms importante de toda la clase" el mtodo action)erformed/0 %ue define y esta&lece las acciones a realiar cuando se presiona el &otn (guardar4uenta(: pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ guardar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.nom&re Q Hnom&re.getHext/0O Lou&le p Q neJ Lou&le/Hpeso.getHext/00O archivo.peso Q p.dou&le8alue/0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( guardado exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S )ara comprender ste mtodo lo vamos a ir analiando cada ve ms profundamente" primero tenemos un ifVelse %ue vamos a (vaciar( para visualiarlo mejor: if/e.getSource/0 QQ guardar4uenta KK Hnumero.getHext/0 +Q ((0 P S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S El operador $9L KK /do&le ampersand0 indica %ue de&en cumplirse las dos condiciones para %ue el primer if se ejecute" la primera condicin verifica el origen del evento" la funcin getSource/0 regresa el nom&re del o&jeto so&re el cual se hio el evento y si este coincide con el nom&re de nuestro &otn llamado (guardar4uenta( significa %ue el evento se origin en l. !a segunda condicin verifica %ue el contenido del campo de texto nom&rado (Hnumero( sea desigual a una cadena vaca" la funcin getHext/0 o&tiene el contenido del campo" es decir" regresa el String %ue contiene" creo %ue es ms %ue o&vio %ue necesitamos antes %ue nada el n#mero de cuenta %ue deseamos guardar por lo tanto no se puede si %uiera entrar a este if sin este dato. En el caso de %ue ninguna de las dos condiciones anteriores se cumpla se ejecuta el contenido del else: primero se fija al campo de texto Hnumero el texto (Escri&e algo+( y la funcin select$ll/0 remarca este contenido para resaltarlo y llamar la atencin del usuario para %ue lo modifi%ue" siempre %ue este else se ejecute significa %ue el usuario olvid escri&ir un n#mero de cuenta. $hora veamos el contenido interno del ifVelse %ue se ejecuta en caso de %ue la condicin del anterior se cumpla" justamente se trata de otro &endito ifVelse: if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S )ara este ifVelse tenemos otro operador $9L KK %ue devuelve un true solo si las dos condiciones son verdaderas" en pocas pala&ras se revisa si el entero en el campo del n#mero de cuenta esta entre ; y ;<< ya %ue la idea es %ue nuestro archivo contenga solo ;<< clientes como mximo" si se dan cuenta ya podemos calcular el tama.o del archivo final" cada registro es de ,B &ytes y si tenemos ;<< registros el archivo final ser de ;<<x,B Q ,B<< &ytes %ue tam&in es igual a /.0b" es muy pe%ue.ito" perfecto++. !a funcin parseInt de la clase Integer convierte cadenas a enteros" en esta ocasin la cadena %ue se reci&e es la contenida en el campo de texto (Hnumero(. Si resulta %ue el entero no es mayor a cero y adems tampoco es menor a ;<; entonces se ejecuta el (else(" este pide al usuario %ue escri&a un n#mero de cuenta entre ; y ;<<" tam&in resalta este texto para recalcar el mensaje mediante la funcin select$ll/0. )or #ltimo examinemos el contenido ms interno de este ifVelse %ue o&viamente se ejecutar solo si la condicin del ifVelse anterior se cumple: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.nombre 1 4nombre.get4e)t356 'ouble p 1 ne7 'ouble34peso.get4e)t3556 archivo.peso 1 p.double8alue356 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.escribir356 4numero.set4e)t3((56 4nombre.set4e)t3((56 4peso.set4e)t3((56 S,stem.out.println3("egistro ( : 3archivo.numero $ 15 : ( guardado e)itosamente(56 $%u conviene recordar lo %ue haca el mtodo escri&ir/0 de la clase cuenta'egistro" ste mtodo toma&a los valores almacenados en sus varia&les glo&ales (numero(" (nom&re( y (peso( para almacenarlos en forma de &ytes de manera ordenada lo cual significa %ue antes de pretender escri&ir de&emos pasarle estos valores. !as primeras lneas /en rojo0 se encargan #nicamente de eso: de pasar los valores contenidos en los campos de te)to hacia las variables globales de una cuenta"egistro nombrada como archivo" noten %ue como estas varia&les son pu&lic significa %ue podemos acceder a ellas li&remente mediante el operador punto" primero se pasa el n#mero" despus la cadena %ue contiene el nom&re del cliente y por #ltimo su saldo" a%u recurrimos /al igual %ue en la seccin de aplicaciones" cosa %ue puedes consultar0 a la clase Lou&le para convertir un valor String o&tenido del campo a un dou&le" un Lou&le es similar aun%ue no es lo mismo %ue un dou&le /con d min#scula0" un Lou&le solo nos sirve de punte para convertir un String a un dou&le. 'ecurrimos al constructor de Lou&le %ue reci&e una cadena como argumento para tomar el valor dou&le de dicha cadena mediante la funcin dou&le8alue/0. En el cdigo intermedio /marcado en aul marino0 se tiene el desplaamiento de nuestro lapicito mediante la funcin seeM hacia el rengln adecuado" esta funcin reci&e como argumento un n#mero de tipo long" como nuestras varia&les de n#mero de cuenta y de tama.o son enteros estos de&en ser convertidos a long /de ah la pala&ra long entre parntesis0 se supone %ue cada rengln tiene una cuenta de un solo cliente completa" si tenemos ;<< renglones cada uno con ,B &ytes de longitud significa %ue cada desplaamiento de&e ser #nicamente de m#ltiplos de ,B" para eso es la varia&le constante sie++. )or ejemplo si deseamos escri&ir en la cuenta n#mero -- tenemos %ue desplaarnos a la lnea -- pero cada lnea mide ,B &ytes es decir %ue en realidad nos desplaamos --x,B Q ;=;C &ytes totales. Si deseamos escri&ir en la #ltima cuenta entonces nos desplaamos: AAx,B Q ,;:@ &ytes" si deseamos escri&ir en la primera cuenta nos desplaamos <x,B Q < &ytes" sin em&argo las cuentas comienan desde ; y terminan en ;<< pero los registros comienan en < y terminan en AA" de ah %ue se le tenga %ue restar siempre un uno a la varia&le %ue almacena el n#mero de cuenta: archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.escribir356 Si ya o&tuvimos los datos y ya desplaamos nuestro lapicito hacia la posicin correcta entonces es momento de escri&ir llamando a la funcin escri&ir/0 de la case cuenta'egistro. F si ya guardamos los datos ahora tenemos %ue limpiar los campos de texto para o&tener nuevos datos" esto se logra con: 4numero.set4e)t3((56 4nombre.set4e)t3((56 4peso.set4e)t3((56 S,stem.out.println3("egistro ( : 3archivo.numero $ 15 : ( guardado e)itosamente(56 El System.out.println/0 reci&e una cadena como argumento" recuerden %ue este mensaje es puramente informativo para indicar en la consola del sistema %ue por lo menos hasta a%u todo se ha ejecutado &ien. Esta clase solo es un Drame" no es un programa independiente. ?s adelante veremos como cargarla desde el programa principal y se supone %ue se ver algo as: La clase (baja( !a siguiente clase es casi igual %ue la anterior" incluye un po%uitito ms de cdigo" a#n as su explicacin ser ms &reve. Esta clase hereda de Drame para mostrar una ventana con una interfa grfica sencilla %ue nos permita dar de &aja una cuenta. 4omo de costum&re les muestro el cdigo y al final su explicacin: import java.aJt.NO import java.aJt.event.NO pu&lic class &aja extends Drame implements $ction!istener P !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O Eutton eliminar4uenta Q neJ Eutton/(Eliminar4uenta(0O cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O pu&lic &aja/0 P super/(Eaja de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O add/eliminar4uenta0O eliminar4uenta.setEna&led/false0O &uscar4uenta.add$ction!istener/this0O eliminar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O eliminar4uenta.setEna&led/true0O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else if/ e.getSource/0 QQ eliminar4uenta 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.numero Q <O archivo.nom&re Q ( (O archivo.peso Q <.<O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O eliminar4uenta.setEna&led/false0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( &orrado exitosamente(0O S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S S E)plicacin de la clase (baja( )rimero importamos los pa%uetes %ue vamos a utiliar" heredamos de la clase Drame e implementamos la interfa $ction!istener para manejar el evento %ue generen los &otones: import java.aJt.NO import java.aJt.event.NO pu&lic class &aja extends Drame implements $ction!istener P Leclaramos nuestros componentes para la interfa grfica con el usuario" son casi los mismos %ue en la clase anterior" lo #nico %ue cam&ia es %ue ahora son dos &otones" el primero nos permitir &uscar la cuenta a eliminar y se supone %ue cuando se presiona se mostrar la informacin de dicha cuenta a modo de confirmacin visual y una ve confirmado se activar el &otn eliminar. !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O Eutton eliminar4uenta Q neJ Eutton/(Eliminar4uenta(0O 4reamos una nueva cuenta'egistro en modo lecturaVescritura: cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O Lefinimos el constructor llamando al constructor de nuestra superclase Drame mediante (super(. Especificamos un nuevo !ayout /acomodamiento0" fijamos la posicin y el tama.o de la ventana con setEounds/0" agregamos los componentes en orden y agregamos los !isteners a los componentes correspondientes /a la ventana y a los &otones0" es muy importante %ue hasta el final ya %ue todo este configurado y definido plenamente se exhi&a el Drame mediante set8isi&le/true0: pu&lic &aja/0 P super/(Eaja de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O add/eliminar4uenta0O eliminar4uenta.setEna&led/false0O &uscar4uenta.add$ction!istener/this0O eliminar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S Lefinimos la clase interna %ue se encarga de cerrar el evento heredando de la clase a&stracta UindoJ$dapter %ue a su ve hereda de UindoJ!istener: pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S 1ff" por fin llegamos a lo &ueno" el mtodo action)erformed. $l igual %ue con la explicacin anterior vamos a recorrer estructura por estructura cada ve ms internamente estudindola paso a paso. pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < XX Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O eliminar4uenta.setEna&led/true0O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else if/ e.getSource/0 QQ eliminar4uenta 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.numero Q <O archivo.nom&re Q ( (O archivo.peso Q <.<O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O eliminar4uenta.setEna&led/false0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( &orrado exitosamente(0O S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S Lentro de esta funcin tenemos un ifVelse anidado /uno dentro de otro0" el ms exterior contiene dos condiciones y un else mientras %ue el ms interno posee una condicin y un else" primero vamos a ver el exterior: if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P S else if/ e.getSource/0 QQ eliminar4uenta 0 P S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S !a primera condicin esta en funcin de dos condiciones con el operador KK /do&le ampersand0 e.getSource/0 o&tiene el nom&re del componente u o&jeto so&re el cual se hio la accin y si este coincide con el &otn (nom&rar4uenta( significa %ue dicho &otn se ha oprimido" Hnumero.getHext/0 +Q (( comprue&a %ue el contenido del n#mero de cuenta no este vaco" la segunda condicin de este if comprue&a si se ha oprimido el segundo &otn mediante otro getSource/0 solo %ue esta ve lo compara con el nom&re (eliminar4uenta(. El else del final maneja el caso en %ue no se haya escrito ning#n n#mero y se haya oprimido &uscar4uenta" o&viamente es imposi&le determinar la cuenta sin el n#mero+. $hora veamos el ifVelse %ue se encuentra dentro de la primera condicin del otro &endito ifVelse ms exterior: if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S Esto hace exactamente lo mismo %ue la condicin vista para la clase (alta(. Se revisa el n#mero de cuenta para proceder solo si esta entre ; y ;<<. El (else( muestra un mensaje en caso de %ue no hayas introducido el n#mero correctamente. $hora veamos el contenido del if anterior %ue con mucho es la parte ms interesante de toda esta clase: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.leer356 4numero.set4e)t3String.valueO;3archivo.numero556 4nombre.set4e)t3archivo.nombre56 4peso.set4e)t3String.valueO;3archivo.peso556 eliminar&uenta.setEnabled3true56 S,stem.out.println3("egistro ( : 3archivo.numero $15 : ( leido e)itosamente(56 >&serva cuidadosamente %ue para llegar a la seccin de cdigo anterior se tuvo %ue ha&er cumplido /por los ifVelse0 %ue el &otn presionado sea &uscar4uenta y %ue el n#mero de cuenta haya estado entre ; y ;<<. El cdigo en rojo se encarga de o&tener el n#mero de cuenta %ue se pretende &uscar directamente desde el campo de texto correspondiente. El cdigo en aul se encarga de colocar nuestro lapicito de lectura en la cuenta apropiada multiplicando los ,B &ytes de la varia&le constante sie de la clase cuenta'egistro nom&rada (archivo( por el n#mero de cuenta menos uno" ya dijimos %ue esta resta se de&e a %ue la primera cuenta comiena en cero" no en uno+. 1na ve colocado el puntero de lectura en la posicin correcta del archivo ahora podemos proceder a leer la informacin mediante la funcin leer/0 de la clase cuenta'egistro /seccin de cdigo en verde0" si esta operacin se realia apropiadamente significa %ue los valores tomados del archivo se almacenaron en las varia&les glo&ales de la clase cuenta'egistro y por lo tanto podemos tomarlos li&remente con el operador punto tal como se o&serva" estos valores inmediatamente se fijan a los campos de texto mediante setHext/0" para esto el n#mero de cuenta de&e ser convertido a cadena mediante la funcin String.value>f/0" lo mismo para el valor dou&le del peso" el nom&re ya es una cadena+ por lo tanto no es necesario convertirlo. )or #ltimo en p#rpura activamos el &otn (eliminar4uenta(" este &otn inicialmente aparece desactivado como se ve en la siguiente figura: 6)or%u inicialmente de&e estar desactivado este &otn7 por%ue antes de &orrar cual%uier cuenta el programa de&e sa&er su n#mero" adems es muy recomenda&le exhi&ir los datos %ue se pretenden &orrar a modo de confirmacin visual" solo hasta ese momento ser posi&le &orrar la cuenta por eso el &otn de &orrado solo se activa hasta los datos se han ledo exitosamente. El System.out.println/0 tiene como propsito exhi&ir un mensaje en la consola /desde L>S0 %ue indi%ue el n#mero de registro %ue se ha ledo. $hora revisemos el contenido de la segunda condicin del ifVelse ms exterior %ue se encarga de &orrar la cuenta: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.numero 1 .6 archivo.nombre 1 ( (6 archivo.peso 1 ...6 archivo.escribir356 4numero.set4e)t3((56 4nombre.set4e)t3((56 4peso.set4e)t3((56 eliminar&uenta.setEnabled3;alse56 S,stem.out.println3("egistro ( : 3archivo.numero $ 15 : ( borrado e)itosamente(56 >&serven %ue para llegar a%u solo se re%uiere %ue el &otn &orrar4uenta sea oprimido" como este &otn solo se activa mediante la &#s%ueda de una cuenta o&ligamos al usuario a realiar dicha &#s%ueda antes de intentar &orrar cual%uier cuenta. El cdigo en rojo o&tiene el n#mero de cuenta %ue pretendemos &orrar y despus llama a la funcin seeM de la clase cuenta'egistro para colocar en la posicin apropiada nuestra lapicito de escritura. 1na ve en la posicin correcta de nuestro archivo asignamos a las varia&les glo&ales de cuenta'egistro valores (vacos( para so&rescri&ir los datos existentes de modo %ue desaparecan los anteriores" como n#mero de cuenta se asigna un cero" como nom&re una cadena vaca de B< caracteres y como peso cero punto cero" acepto %ue no es del todo necesario &orrar el n#mero de cuenta por%ue de hecho cuando se ingrese otro dato se colocar exactamente el mismo n#mero de cuenta %ue ha&a antes /solo cam&iar el nom&re y el peso0 pero es mejor hacerlo por consistencia" por #ltimo se llama a la funcin escri&ir/0 de la clase cuenta'egistro. El cdigo en aul cielo limpia los campos de texto de los datos y desactiva el &otn de &orrado mediante la funcin setEna&led/0 %ue reci&e un &olean como argumento" con esto o&ligamos otra ve al usuario a realiar la &#s%ueda antes de intentar &orrar otra cuenta. Esta fue toda la clase (&aja(" por si acaso les recuerdo %ue esta clase solo es un Drame" no una aplicacin. ?s adelante veremos %ue esta clase es llamada desde el programa principal. La clase (consulta( !a siguiente clase tiene como propsito realiar consultas rpidas de solo lectura" afortunadamente para nosotros es sumamente simple" se parece mucho a las anteriores" veamos el cdigo y al final su explicacin: import java.aJt.NO import java.aJt.event.NO pu&lic class consulta extends Drame implements $ction!istener P !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (r(0O pu&lic consulta/0 P super/(4onsulta de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O &uscar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S S E)plicacin de la clase (consulta( )rimero heredamos los pa%uetes para interfa grfica y para eventos: import java.aJt.NO import java.aJt.event.NO Lespus heredamos de la clase Drame e implementamos la interfa $ction!istener %ue definir las acciones a realiar una ve atrapado el evento: pu&lic class consulta extends Drame implements $ction!istener P $hora declaramos e inicialiamos los componentes grficos: !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O 4reamos una nueva cuenta'egistro para a&rir el archivo cuentas.dat en modo de solo lectura por%ue esta clase solo har consultas: cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (r(0O Lefinimos el constructor de la clase %ue configura tanto la interfa grfica como el acomodamiento de los componentes" usamos setEounds/0 para fijar la posicin y el tama.o de la ventana" agregamos los componentes en orden para exhi&irlos apropiadamente: pu&lic consulta/0 P super/(4onsulta de 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O &uscar4uenta.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S $l final del constructor anterior registramos los !isteners al &otn y a la ventana" la siguiente innerclass define la accin a realiar: pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S El mtodo JindoJ4losing/0 especifica %ue el archivo de&e cerrarse y despus %ue la ventana de&e destruirse mediante dispose/0. F ahora llegamos a la parte interesante" la consulta de la informacin del archivo mediante el &otn: pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S Esta pelcula ya la vimos. Se trata del ya familiar ifVelse anidado" otra ve se recurre a getSource/0 para identificar la fuente del evento y a la comparacin del texto contenido en el n#mero de cuenta para compro&ar %ue no este vaco" el ifVelse interno revisa %ue el n#mero de cuenta este entre ;V;<< y en tal caso ejecuta: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.leer356 4numero.set4e)t3String.valueO;3archivo.numero556 4nombre.set4e)t3archivo.nombre56 4peso.set4e)t3String.valueO;3archivo.peso556 S,stem.out.println3("egistro ( : 3archivo.numero $15 : ( leido e)itosamente(56 $%u primero se toma el n#mero de cuenta desde el campo de texto" despus se posiciona el lapicito de lectura en la cuenta correcta /con un m#ltiplo de ,B0 y se toman los datos del archivo con la funcin leer/0. Dinalmente el cdigo en rojo asigna los datos o&tenidos a los campos de texto y el mensaje System.out.println/0 exhi&e un mensaje de xito+" juego de ni.os+. La clase (modi;icar( Este es otro Drame %ue sirve para modificar los datos" esto implica %ue a&riremos el archivo en modo lecturaVescritura (rJ(. 8eamos el cdigo y su explicacin correspondiente: import java.aJt.NO import java.aJt.event.NO pu&lic class modificar extends Drame implements $ction!istener P !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O Eutton guardar4am&ios Q neJ Eutton/(2uardar 4am&ios(0O cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O pu&lic modificar/0 P super/(?odificar 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O add/guardar4am&ios0O guardar4am&ios.setEna&led/false0O &uscar4uenta.add$ction!istener/this0O guardar4am&ios.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O guardar4am&ios.setEna&led/true0O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else if/ e.getSource/0 QQ guardar4am&ios 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.nom&re Q Hnom&re.getHext/0O Lou&le p Q neJ Lou&le/Hpeso.getHext/00O archivo.peso Q p.dou&le8alue/0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O guardar4am&ios.setEna&led/false0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( cam&iado exitosamente(0O S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S S E)plicacin de la clase (modi;icar( )rimero importamos el pa%uete aJt /a&stract JindoJ toolMit0 y el de eventos" heredamos de la clase Drame e implementamos un $ction!istener %ue definir los eventos atrapados: import java.aJt.NO import java.aJt.event.NO pu&lic class modificar extends Drame implements $ction!istener P $hora declaramos e inicialimos los componentes %ue vamos a utiliar: !a&el !numero Q neJ !a&el/(9#mero:(0O !a&el !nom&re Q neJ !a&el/(9om&re: (0O !a&el !peso Q neJ !a&el/()eso:(0O HextDield Hnumero Q neJ HextDield/0O HextDield Hnom&re Q neJ HextDield/0O HextDield Hpeso Q neJ HextDield/0O Eutton &uscar4uenta Q neJ Eutton/(Euscar 4uenta(0O Eutton guardar4am&ios Q neJ Eutton/(2uardar 4am&ios(0O F claro tam&in declaramos una nueva cuenta'egistro %ue en esencia es el archivo %ue nos permite leer y escri&ir: cuenta'egistro archivo Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O Lefinimos el constructor y en l configuramos la interfa grfica" registramos los !isteners y por #ltimo hacemos visi&le el Drame con set8isi&le/true0: pu&lic modificar/0 P super/(?odificar 4uenta V 2ym?aster+(0O set!ayout/ neJ 2rid!ayout/ :" B 0 0O setEounds/B<<" ;=<" B:<" ;-<0O add/!numero0O add/Hnumero0O add/!nom&re0O add/Hnom&re0O add/!peso0O add/Hpeso0O add/&uscar4uenta0O add/guardar4am&ios0O guardar4am&ios.setEna&led/false0O &uscar4uenta.add$ction!istener/this0O guardar4am&ios.add$ction!istener/this0O this.addUindoJ!istener / neJ cerrar8entana/0 0O set8isi&le/true0O S $hora declaramos una innerclass %ue define la accin a realiar al cerrar la ventana: cerrar el archivo y destruir el Drame. pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P archivo.cerrar$rchivo/0O dispose/0O S S )or #ltimo tenemos el coran de los eventos para los &otones: el mtodo action)erformed %ue exige la interfa $ction!istener: pu&lic void action)erformed/$ctionEvent e0 P if/e.getSource/0 QQ &uscar4uenta KK Hnumero.getHext/0 +Q ((0 P if/ Integer.parseInt/ Hnumero.getHext/0 0 W < KK Integer.parseInt/ Hnumero.getHext/0 0 T ;<; 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.leer/0O Hnumero.setHext/String.value>f/archivo.numero00O Hnom&re.setHext/archivo.nom&re0O Hpeso.setHext/String.value>f/archivo.peso00O guardar4am&ios.setEna&led/true0O System.out.println/('egistro ( 5 /archivo.numero V;0 5 ( leido exitosamente(0O S else P Hnumero.setHext/(Escri&e entre ; y ;<<(0O Hnumero.select$ll/0O S S else if/ e.getSource/0 QQ guardar4am&ios 0 P archivo.numero Q Integer.parseInt/ Hnumero.getHext/0 0O archivo.nom&re Q Hnom&re.getHext/0O Lou&le p Q neJ Lou&le/Hpeso.getHext/00O archivo.peso Q p.dou&le8alue/0O archivo.seeM//long0 /archivo.numero V ;0Narchivo.sie 0O archivo.escri&ir/0O Hnumero.setHext/((0O Hnom&re.setHext/((0O Hpeso.setHext/((0O guardar4am&ios.setEna&led/false0O System.out.println/('egistro ( 5 /archivo.numero V ;0 5 ( cam&iado exitosamente(0O S else P Hnumero.setHext/(Escri&e algo+(0O Hnumero.select$ll/0O S S Este mtodo es casi igual al %ue escri&imos para la clase (consulta(" tenemos un ifVelse anidado /uno dentro de otro0" el ms exterior tiene dos condiciones" la primera es %ue el event provenga del &otn (&uscar4uenta( y adems %ue el n#mero de cuenta no este vaco" en su interior tenemos otro ifVelse %ue tiene como condicin %ue el n#mero de cuenta este entre ; y ;<<. Si lo anterior se cumple /lo cual significa %ue estamos o&teniendo la cuenta %ue pretendemos modificar0 entonces se ejecuta: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.leer356 4numero.set4e)t3String.valueO;3archivo.numero556 4nombre.set4e)t3archivo.nombre56 4peso.set4e)t3String.valueO;3archivo.peso556 guardar&ambios.setEnabled3true56 S,stem.out.println3("egistro ( : 3archivo.numero $15 : ( leido e)itosamente(56 !a seccin en verde del cdigo anterior pasa el entero del campo de texto del n#mero de cuenta hacia la varia&le glo&al (numero( de la clase cuenta'egistro. Lespus llama al mtodo seeM %ue se encarga de colocar el lapicito /%ue en este caso nos servir para leer0 en la posicin correcta dentro del archivo. En rojo iniciamos leyendo el contenido del archivo y despus pasamos los valores ledos y contenidos en las varia&les glo&ales de cuenta'egistro hacia todos y cada uno de los campos de texto. )or #ltimo activamos el &otn (guardar4am&ios(" nuevamente al igual %ue en la clase (&aja( o&ligamos al usuario a o&tener la cuenta antes de modificarla activando y desactivando la posi&ilidad de usar los &otones solo cuando se tenga una confirmacin visual" en este caso es a#n ms importante hacer esto. 1na ve o&tenida la cuenta anterior ahora se activa el &otn guardar4am&ios" si oprimimos este &otn se ejecuta el contenido de la segunda condicin del ifVelse superior: archivo.numero 1 2nteger.parse2nt3 4numero.get4e)t35 56 archivo.nombre 1 4nombre.get4e)t356 'ouble p 1 ne7 'ouble34peso.get4e)t3556 archivo.peso 1 p.double8alue356 archivo.see033long5 3archivo.numero $ 159archivo.size 56 archivo.escribir356 4numero.set4e)t3((56 4nombre.set4e)t3((56 4peso.set4e)t3((56 guardar&ambios.setEnabled3;alse56 S,stem.out.println3("egistro ( : 3archivo.numero $ 15 : ( cambiado e)itosamente(56 !a seccin en rojo del cdigo anterior se encarga a grandes rasgos de tomar los valores de los campos de texto y pasarlos hacia las varia&les glo&ales de la clase cuenta'egistro cuyo nom&re es archivo" nuevamente recurrimos al puente Lou&le %ue nos permite convertir una cadena en un valor dou&le /recuerden %ue aun%ue son similares no son iguales0. El cdigo en aul oscuro desplaa el puntero o lapicito para escri&ir en la lnea correcta de nuestro archivo" este desplaamiento siempre es en m#ltiplos de ,B &ytes por eso se multiplica por la varia&le sie de la clase cuenta'egistro. El cdigo verde limpia los campos de texto justo despus de %ue se ha escrito y finalmente desactiva el &otn guardar4am&ios para o&ligar al usuario a localiar otra cuenta antes de intentar modificarla. La clase (archivosAleatorios( 3Programa Principal5 Guis podramos sospechar %ue el programa principal %ue cargar las cinco clases anteriores podra ser &astante extenso y complejo pero no es as" es muy simple+" o&serven la clase y noten %ue posee el mtodo main/0 %ue lo define como una verdadera aplicacin independiente" al final explico su cdigo: import java.aJt.NO import java.aJt.event.NO import java.io.DileO pu&lic class archivos$leatorios extends Drame implements $ction!istener P Eutton alta Q neJ Eutton/($lta de 4uenta(0O Eutton &aja Q neJ Eutton/(Eaja de 4uenta(0O Eutton modif Q neJ Eutton/(?odificar 4uenta(0O Eutton cons Q neJ Eutton/(4onsulta 'pida(0O alta aO &aja &O modificar mO consulta cO pu&lic archivos$leatorios/0 P super/(2ym?aster+(0O set!ayout/neJ 2rid!ayout/ B" B" ;<" ;< 00O setEounds/B<<" ;,<" B,<" ;-<0O this.addUindoJ!istener / neJ cerrar8entana/0 0O add/alta0O add/modif0O add/&aja0O add/cons0O alta.add$ction!istener/this0O modif.add$ction!istener/this0O &aja.add$ction!istener/this0O cons.add$ction!istener/this0O set8isi&le/true0O S pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P dispose/0O System.exit/<0O S S pu&lic void action)erformed/$ctionEvent event0 P System.gc/0O if/event.getSource/0 QQ alta0 P a Q neJ alta/0O S else if /event.getSource/0 QQ &aja0 P & Q neJ &aja/0O S else if /event.getSource/0 QQ modif0 P m Q neJ modificar/0O S else if /event.getSource/0 QQ cons0 P c Q neJ consulta/0O S S pu&lic static void main/String argsY Z0 P try P Dile cuentas Q neJ Dile/(cuentas.dat(0O if/cuentas.exists/0 QQ false0 P cuenta'egistro ' Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O for/int i Q <O i T ;<<O 55i0 '.escri&ir/0O '.cerrar$rchivo/0O System.out.println/(El archivo cuentas.dat no existia" fue creado exitosamente(0O S else P System.out.println/(1sando el archivo de cuentas existente(0O S S catch /9ull)ointerException e0 P System.out.println/(9o diste el nom&re del archivo a verficar si existe+( 5 e.toString/00O S archivos$leatorios f Q neJ archivos$leatorios/0O S S E)plicacin de la aplicacin (archivosAleatorios( $ntes de continuar hay %ue aclarar ciertas cuestiones importantes. Primero esta clase tam&in heredar de un Drame as %ue ser una ventana %ue exhi&a los &otones principales asociados con cada una de las cuatro principales acciones: $lta de cuenta" Eaja de 4uenta" ?odificacin de cuenta y 4onsulta 'pida de una cuenta. Segundo" esta clase har uso de la clase Dile para checar si existe el archivo (cuentas.dat(" si el archivo ya existe entonces no se tocar para dejarlo tal cual y as las otras clases lo puedan utiliar sin ning#n tipo de modificacin. Si el archivo no existe entonces de&e ser (cuadriculado( /para definir su tama.o0 con los datos %ue pretendemos almacenar /es decir: un int" una String y un dou&le0" este cuadriculado se logra recurriendo nuevamente a la clase (cuenta'egistro( como veremos ms adelante. F 4ercero cada Drame creado anteriormente: (alta(" (&aja(" (consulta( y (modificar( posee la capacidad de cerrarse solo as %ue este programa no necesita preocuparse de eso" solo de&e ocuparse de crearlos cuando se oprima el &otn correspondiente" lo mismo sucede con la lectura yRo escritura en el archivo" eso es asunto personal de cada Drame %ue no tiene nada %ue ver con el siguiente programa principal+. )rimero importamos el pa%uete del $&stract UindoJ HoolMit" el de eventos y la clase Dile: import java.aJt.NO import java.aJt.event.NO import java.io.DileO $hora heredamos de un Drame e implementamos la interfa $ction!istener %ue definir la accin asociada con los eventos en los &otones: pu&lic class archivos$leatorios extends Drame implements $ction!istener P Leclaramos e inicialiamos cuatro &otones" la idea es %ue cada uno llame a las otras clases creadas anteriormente: Eutton alta Q neJ Eutton/($lta de 4uenta(0O Eutton &aja Q neJ Eutton/(Eaja de 4uenta(0O Eutton modif Q neJ Eutton/(?odificar 4uenta(0O Eutton cons Q neJ Eutton/(4onsulta 'pida(0O Leclaramos solamente /sin inicialiar a#n0 cuatro tipos de las clases ya creadas con nom&res &astante simples: alta aO &aja &O modificar mO consulta cO Lefinimos el constructor de nuestro programa principal %ue configura toda la interfa grfica: pu&lic archivos$leatorios/0 P super/(2ym?aster+(0O set!ayout/neJ 2rid!ayout/ B" B" ;<" ;< 00O setEounds/B<<" ;,<" B,<" ;-<0O this.addUindoJ!istener / neJ cerrar8entana/0 0O add/alta0O add/modif0O add/&aja0O add/cons0O alta.add$ction!istener/this0O modif.add$ction!istener/this0O &aja.add$ction!istener/this0O cons.add$ction!istener/this0O set8isi&le/true0O S )rimero se llama al constructor de Drame mediante super/0 y se le pasa el ttulo como argumento" despus fijamos un nuevo acomodamiento con set!ayout/0 %ue ser un nuevo 2rid!ayout con dos lneas y dos columnas" el tercer y cuarto argumento de este constructor son las separaciones horiontal y vertical entre componentes respectivamente" setEounds/0 nos permite fijar la colocacin y el tama.o de la ventana y se agrega un nuevo UindoJ!istener a la ventana cuya accin esta definida en la siguiente innerclass: pu&lic class cerrar8entana extends UindoJ$dapter P pu&lic void JindoJ4losing/UindoJEvent e0 P dispose/0O System.exit/<0O S S En esta ocasin no solo se cerrar el Drame" tam&in se cerrar completamente el programa mediante la llamada a: System.exit/<0O El siguiente es el mtodo action)erformed %ue es impresionantemente simple /gracias a %ue definimos cada Drame de (alta(" (&aja(" (modificar( y (consulta( de manera independiente0: pu&lic void action)erformed/$ctionEvent event0 P if/event.getSource/0 QQ alta0 P a Q neJ alta/0O S else if /event.getSource/0 QQ &aja0 P & Q neJ &aja/0O S else if /event.getSource/0 QQ modif0 P m Q neJ modificar/0O S else if /event.getSource/0 QQ cons0 P c Q neJ consulta/0O S S Nota* 9o de&en confundir el nom&re de los &otones con el nom&re de las clases (alta(" (&aja(" (modificar( y (consulta(" son cosas totalmente diferentes+. 4omo para exhi&irlos solo &asta llamar a su constructor puesto %ue cada uno se configura a s mismo" as de fcil++. Solo tenemos cuatro &otones" el ifVelse anterior verifica de dnde proviene el evento generado y si el o&jeto cuyo nom&re es el &otn (alta( entonces se crea un nuevo o&jeto de tipo alta mediante su constructor" si el &otn de donde proviene el evento es el nom&rado como (&aja( entonces se crea un nuevo o&jeto &aja y as sucesivamente. $hora el mtodo main %ue es el encargado de cargar este Drame principal y el %ue revisa si es %ue el archivo (cuentas.dat( existe o no: pu&lic static void main/String argsY Z0 P try P Dile cuentas Q neJ Dile/(cuentas.dat(0O if/cuentas.exists/0 QQ false0 P cuenta'egistro ' Q neJ cuenta'egistro/(cuentas.dat(" (rJ(0O for/int i Q <O i T ;<<O 55i0 '.escri&ir/0O '.cerrar$rchivo/0O System.out.println/(El archivo cuentas.dat no existia" fue creado exitosamente(0O S else P System.out.println/(1sando el archivo de cuentas existente(0O S S catch /9ull)ointerException e0 P System.out.println/(9o diste el nom&re del archivo a verficar si existe+( 5 e.toString/00O S archivos$leatorios f Q neJ archivos$leatorios/0O S )rimero creamos un nuevo Dile tomando como argumento para su constructor el nom&re del archivo (cuentas.dat(" este constructor puede lanar diversos tipos de excepciones %ue pueden ser atrapadas como un 9ull)ointerException tal como se ve. Lespus tenemos el ifVelse %ue revisa si el archivo (cuentas.dat( ya esta presente o no mediante la funcin exists/0 de la clase Dile" si no existe entonces creamos un nuevo cuentas'egistro nom&rado ' y escri&imos en l cien registros vacos" terminada la escritura cerramos el archivo y mostramos un anuncio de %ue el archivo se creo correctamente. )or #ltimo llamamos al constructor de esta clase (archivos$leatorios(" recuerden %ue el mtodo main es como si fuera una seccin independiente de la clase %ue es llamada por el intrprete *ava por eso es posi&le llamar el constructor dentro de la misma clase. El mtodo main es lo primero %ue se &usca al ejecutar un programa independiente escrito en *ava. Si todo sale &ien entonces ya pueden correr la aplicacin %ue se ver algo as: >riginalmente no hay archivo (cuentas.dat(" as %ue se supone %ue de&es introducir algunas cuentas /darlas de alta0 para despus pro&ar con ellas ya sea una &aja" una modificacin o una consulta. $ modo de confirmacin o&serven %ue al consultar las propiedades del archivo (cuentas.dat( podemos notar %ue su tama.o coincide con todas las suposiciones so&re conversin a &ytes para los tipos de datos" tenemos ;<< clientes" cada cliente tiene: cuenta" nom&re y peso /,B&ytes0 ;<<x,B Q ,B<< &ytes. El cdigo de este programa no es mucho sin importar lo grande %ue pareca esta seccin" un programa de este tipo con prctica sale cuando mucho en B horas y eso exageradamente+ a#n as les pongo el cdigo en ip si desean ahorrarse codificar todo: 4digo del )rograma Ejemplo /2ym?aster+0 2racias a *ava tenemos ms posi&ilidades" cada uno de ustedes fijar su propio lmite. Experimenta++ pero so&re todo: nunca olvides %ue aprender siempre puede ser divertido++ #in del &ap<tulo Siete = Archivos de Acceso Aleatorio