Você está na página 1de 5

Archivos de Acceso Directo

Objetivos: Mostrar que los archivos tambin se pueden accesar en forma no secuencial y
que esto es til para no tener que visitar completamente archivos de gran tamao.
Temas:

Archivos de acceso directo.


Bsqueda binaria en un archivo de acceso directo.

La clase RandomAccessFile.

Archivos de acceso directo


En muchos problemas de manejo de informacin, se debe reunir la informacin que aparece
en dos archivos. Como se dijo en el captulo anterior, el pareo de ambos archivos ordenados
segn un mismo campo es una solucin eficiente. Sin embargo existe un caso en donde esta
solucin no es la mejor: cuando uno de los archivos es mucho ms pequeo que el otro.
Cuando uno de los archivos contiene un nmero reducido de lneas resulta ms eficiente
emplear archivos de acceso directo, porque permiten reunir la informacin sin tener que
visitar el archivo completo.
Motivacin:
Para ejemplificar esta situacin, consideraremos el archivo de postulantes del captulo
anterior. El problema consistir en obtener los nombres de unos 100 postulantes de los
cuales slo se tiene el carnet de identidad en el archivo carnets.dat. El archivo de
postulantes es lo suficientemente grande como para que su contenido no quepa en la
memoria del computador.
Definiciones:
Un archivo se accesa secuencialmente cuando el programa que lo utiliza ya sea lo lee o lo
escribe en forma secuencial. Hasta el momento slo hemos visto programas que accesan
secuencialmente los archivos.
Un archivo se accesa directamente cuando el programa que lo utiliza especifica
directamente la posicin dentro del archivo que se accesar. Por ejemplo el programa puede
leer la lnea nmero 200, luego la lnea 50000 y ms tarde la lnea 1.
Es importante notar que para el sistema operativo todos los archivos pueden ser accesados
directamente. Sin embargo, es muy difcil accesar directamente los archivos de texto que
hemos usado hasta el momento, porque sus lneas tienen largo variable.

Para que un archivo se pueda accesar cmodamente en forma directa, es necesario que sus
lneas tengan un nmero fijo de caracteres. Por esta razn, los archivos de acceso directo
que usaremos en los ejemplos, tendrn la extensin ".raf". Lamentablemente, estos archivos
no pueden ser vistos mediante WordPad o NotePad porque su contenido no es
necesariamente desplegable en pantalla.

Bsqueda binaria en un archivo de acceso directo


Para resolver el problema que nos motiva, supondremos que existe una clase PostRAF que
permite hacer accesos directos en archivos de postulantes con la extensin ".raf". Ms tarde
implementaremos esta clase.
Ejemplo
Significado
Declaracin
PostRAF praf= new
PostRAF("post.raf");

Construye un lector/escritor de
acceso directo para post.raf

PostRAF(String arch)

Post post= praf.leer(30);

Entrega el postulante nmero 30

Post leer(int nro)

praf.escribir(50, post2);

Escribe el postulante post2 en la


posicin 50

void escribir(int nro,


Post post)

int tamao= praf.tamao();

Entrega el nmero de postulantes


en el archivo

int tamao

praf.close();

Cierra el archivo

void close()

Ejemplo de uso: convertir el archivo post.dat al archivo de acceso directo post.raf.


TextReader lect= new TextReader("post.dat", ":");
PostRAF postRaf= new PostRAF("post.raf");
int i= 0;
while (!lect.eofReached()) {
Post post= new Post(lect);
postRaf.escribir(i, post);
i++;
}
println("leidos y escritos: "+i);
lect.close();
postRaf.close();

El siguiente programa resuelve el problema de la motivacin:


PostRAF postRaf= new PostRAF("post.raf");
TextReader lect= new TextReader("carnets.dat", ":");
TextWriter escr= new TextWriter("nombres.dat", ":");
while (!lect.eofReached()) {
String ci= lect.readString();
Post post= buscar(ci, postRaf);
if (post!=null)
post.escribir(escr);
else
println("no se encontro: "+ci);
}

postRaf.close();
lect.close();
escr.close();

Suponiendo que el archivo post.raf est ordenado por carnet, la funcin buscar puede
realizar una bsqueda binaria:
Post buscar(String ci, PostRAF postRaf) {
int imin= 0;
int imax= postRaf.tamao()-1;
while (imin<=imax) {
int icentro= (imin+imax)/2;
Post post= postRaf.leer(icentro);
int comp= compare(ci, post.ci)
if (comp==0)
return post;
else if (comp<0)
imax= icentro-1;
else
imin= icentro+1;
}
return null;
}

La clase RandomAccessFile
La clase RandomAccessFile permite accesar archivos en forma directa. Esta clase permite
ver un archivo como un arreglo de caracteres y leer o escribir zonas del arreglo. Como lo
indica la siguiente figura, cada caracter se subindica mediante un ndice.

Existe un puntero nico que indica la posicin del archivo que se accesar en la prxima
operacin de lectura o escritura.
La siguiente tabla resume los mtodos principales de la clase:
Ejemplo
RandomAccessFile raf= new
RandomAccessFile("arch.raf", "r");

Significado
Construye un lector
para arch.raf.

Construye un
RandomAccessFile raf2= new
lector/escritor para
RandomAccessFile("arch.raf", "rw");
arch.raf.
raf2.writeUTF("hola");

Declaracin
RandomAccessFile(String
nom, String modo)
RandomAccessFile(String
nom, String modo)

Escribe "hola" en
formato UTF a partir void writeUTF(String s)
de la posicin actual

String s= raf1.readUTF();

Lee un string en
formato UTF a partir String readUTF()
de la posicin actual

raf1.seek(30);

Cambia la posicin
actual del puntero al
ndice 30

void seek(int pos)

int largo= raf1.length();

Entrega el tamao
actual del archivo

int length()

raf.close();

Cierra el archivo

void close()

La operacin writeUTF escribe un string agregando dos caracteres extras en donde se


codifica el largo del string. Adems se avanza el puntero de modo que la prxima escritura
no altere lo que se acaba de escribir:

Del mismo modo, la operacin readUTF determina el largo del string que se va a leer a
partir de los dos primeros bytes (desde la posicin actual):

Con estas operaciones definimos la clase PostRAF de la siguiente manera:

class PostRAF extends Program {


RandomAccessFile raf;
int largo;
int largoci= 10; // 10 caracteres para el ci
int largonombre= 30; // 30 para el nombre
PostRAF(String arch) {
this.raf= new RandomAccessFile(arch, "rw");
this.largo= 2+this.largoci+ 2+this.largonombre;
}
Post leer(int nro) {
this.raf.seek(nro*this.largo);
String ci= trim(this.raf.readUTF());
String nombre= trim(this.raf.readUTF());
return new Post(ci, nombre);
}
void escribir(int nro, Post post) {
this.raf.seek(nro*largo);
this.raf.writeUTF(extender(post.ci, this.largoci));
this.raf.writeUTF(extender(post.nombre, this.largonombre));
}
int tamao() {
return raf.length()/largo;
}
void close() {
raf.close();
}
String extender(String s, int l) {
return s+repeat(" ", l-length(s));
}
}

Você também pode gostar