Sei sulla pagina 1di 36

Archivos de Acceso Aleatorio

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