TEMA 4: Manejo de Archivos
Dentro de este apartado vamos a aprender que son y como
utilizar los archivos. Veremos cual es su finalidad, que tipos son
los más comunes y cuales son sus características principales desde
el punto de vista de la organización de los datos que contiene.
Para comenzar podemos decir que un ordenador que no tiene la
posibilidad de almacenar sus programas y datos en un dispositivo de
almacenamiento, (ya sean discos, cintas, etc.) no es mas que una
calculadora. En la actualidad, cualquier ordenador posee
dispositivos de almacenamiento, ya sean internos (discos duros) o
externos (disquetes, cartuchos, cintas, etc.). La finalidad es
obvia, la de poder guardar los datos para su posterior recuperación
y tratamientos de los mismos en otras sesiones.
Un común error entre los principiantes es el de confundir la
memoria de tipo RAM con la capacidad de almacenamiento del disco que
acompaña al ordenador. La RAM (Memoria de Acceso Aleatorio) es
denominada memoria volátil, ya que una vez que se apaga el ordenador
la información que esta contenía se pierde. La RAM se mide
generalmente en MegaBytes, aunque con el paso del tiempo la unidad
puede cambiar (1 Mb son 1024 Ks, a su vez 1 K es 1024 bytes, y
finalmente 1 Byte son 8 bits, siendo esta última la cantidad mínima
de información que puede procesar un computador). La capacidad de
los dispositivos de almacenamiento (entiéndase disquetes, discos
duros, cintas, CD-ROM, etc.) se mide en las mismas unidades, es por
ello que la gente suele confundir la memoria RAM de un ordenador con
la capacidad de almacenamiento que suele tener en un disco duro.
La memoria RAM es uno de los aspectos que limita la potencia
de un ordenador, cuanta más RAM tengamos, mayores programas y datos
podremos almacenar en ella y menos accesos a los dispositivos de
almacenamiento tendremos que realizar.
Los archivos o ficheros se almacenan en los dispositivos de
almacenamiento, para como dijimos anteriormente puedan ser
recuperados sus datos en sesiones futuras.
De esta forma, podemos definir un fichero como un objeto
concebido para el almacenamiento permanente de la información.
Información que puede ser organizada de diferente forma dependiendo
del trato que le vayamos a dar.
4.1 Nociones de dispositivos de almacenamiento.
En el apartado anterior hemos aprendido que la información
puede ser volcada en dispositivos de almacenamiento permanente, a
los cuales nos hemos referido como disquetes, discos duros, cintas,
CD-ROM, etc.
Estos medios de almacenamiento se pueden diferenciar en el
modo en el que la información puede ser accesible.
Así definimos dispositivos de almacenamiento o soportes
secuenciales a aquellos donde la información es accesible
secuencialmente, es decir, para leer o escribir un dato determinado,
antes tenemos que pasar por todos los datos que le preceden. De esta
forma, en una cinta magnética los datos se graban y leen uno detrás
de otro. Y no podemos ir directamente a uno en concreto sin pasar
antes por los demás.
De igual forma se define soportes direccionables a aquellos
donde la superficie de almacenamiento es independiente e
individualmente direccionable, es decir, podemos acceder a un dato
en concreto sin tener que pasar antes por los demás. Este es el caso
de los discos. Por poner un ejemplo, en un disco de vinilo, podemos
elegir la canción que queremos tan sólo con poner el cabezal en el
comienzo de la misma. Sin embargo, en una cinta de casete, para oír
una canción determinada antes debemos pasar todas las que le
preceden.
En los dispositivos de almacenamientos hay que diferenciar
las direcciones en las que se almacenan los datos. De este modo
tenemos dos tipos de direcciones: direcciones absolutas o físicas y
direcciones relativas o lógicas.
Las direcciones absolutas o físicas son las direcciones con
las que juega el ordenador de forma física en el dispositivo, es
decir, cuando el ordenador se refiere a un dato en concreto lo esta
haciendo por el conocimiento de ciertos datos que identifican la
posición física del dato en el soporte de almacenamiento. Así, el
ordenador juega con parámetros tales como: unidad, cabeza, cara,
pista o cilindro y sector.
Por el contrario, las direcciones relativas o lógicas son
con las que vamos a jugar nosotros, una vez que abrimos el fichero
para realizar operaciones de Input/output (I/O) nos referimos al
dato con un índice numérico, es decir, el registro número x.
4.2 Ficheros de Acceso Secuencial.
Un Fichero de Acceso Secuencial es aquel donde los registros
están ubicados consecutivamente sobre un dispositivo de
almacenamiento. De tal forma que para acceder a un registro
determinado 'd' debemos pasar obligatoriamente por todos los
registros que le preceden.
Suponiendo una cinta magnética, para leer registro 'd'
debemos pasar antes por el 'a', 'b', 'c'.
---------------------- Para leer el registro 'd', la cabeza
+- a b c d ... lectora, deberá pasar antes por los
| ---------------------- que le preceden.
+> cabeza lectora.
Un Fichero de Acceso Secuencial puede ser almacenado tanto
en un dispositivo de almacenamiento direccional como secuencial, sin
embargo los Ficheros de Acceso Directo e Indexado únicamente puede
ubicarse en dispositivos de almacenamiento direccional.
4.2.1 Ejemplo de I/O en Ficheros Secuenciales.
Pasemos a ver un ejemplo de como utilizar ficheros
secuenciales, pero antes veamos las sentencias básicas que
utilizaremos.
- Abrir secuencial (variable)
Esta sentencia abre un fichero para el acceso secuencial.
Donde la variable contiene el nombre del fichero a abrir.
- Cerrar (variable)
Esta sentencia cierra un fichero donde la variable contiene
el nombre del fichero a cerrar.
- Leer/Escribir/Reescribir (variable1,variable2)
Esta sentencia permite la lectura o re/escritura de los
datos que contiene la variable2 en un fichero de nombre, el
determinado en la variable1.
- Iniciar operaciones de lectura y/o escritura en (variable)
Esta sentencia debe incluirse después de abrir un fichero y
determina prácticamente el tipo de acceso que vamos a realizar, es
decir, si abrimos el fichero para leer y/o escribir.
- NO fin (variable)
Esta función devuelve el valor lógico 'true' si no se ha
encontrado el final del fichero; y devuelve el valor lógico 'false'
si se ha encontrado el final del fichero.
- Error (variable)
Esta función devuelve el código del error producido al
realizar cualquier operación anterior. Por defecto, la función
devuelve un cero cuando no se ha producido ningún error.
Ejemplo: En este ejemplo se intenta dar aun visión general del uso
de ficheros secuenciales.
+-Algoritmo Copiar_fichero
|
| Fichero de enteros Origen,Destino
| Variable entera x
|
| Escribir ("Indique el nombre del fichero Origen:");
| Leer Origen
| Escribir ("Indique el nombre del fichero Destino:")
| Leer Destino
|
| Abrir secuencial (Origen)
| Iniciar lectura en (Origen)
| Abrir secuencial (Destino)
| Iniciar escritura en (Destino)
|
| +-Mientras (NO fin(Origen)) hacer
| | Leer (Origen,x)
| | Escribir (Destino,x)
| +-Finmientras
|
| Escribir ("Fichero Copiado:")
|
| Cerrar (Origen)
| Cerrar (Destino)
|
+-Final
Nota: Obsérvese que la variable utilizada en las operaciones
de lectura y/o escritura, deben ser del mismo tipo que la
declaración del fichero.
4.3 Registros Estructurados.
Hasta ahora hemos visto como los registros eran de un tipo
único, es decir, eran todos carácter, enteros, reales, etc. Sin
embargo, hay situaciones en las que debemos realizar agrupaciones de
tipos para formar un registro estructurado. Así, un registro
estructurado esta formado por un conjunto de variables de diferentes
tipos que denominaremos campos. De este modo podemos decir que un
registro estructurado es un conjunto de campos.
Ejemplo:
+-Registro datos-alumno
| Cadena nombre
| Cadena apellido1
| Cadena apellido2
| Cadena NIF
| Cadena curso
| Cadena telefono
| Cadena fecha_nac
| ...
+-Finregistro
De esta forma, podemos leer y escribir en un fichero
registros estructurados que nos permitirán un almacenamiento más
lógico y ordenado de los datos.
Al generar un registro es como si estuviésemos definiendo un
nuevo tipo de variable independiente de las ya existente (enteras,
reales, cadena, etc.).
Este tipo de registros o record se utiliza para agrupar la
información que se desee volcar a un fichero determinado.
4.4 Ficheros de Acceso Directo.
Un Fichero de Acceso Directo (es también denominado de
acceso aleatorio) es aquel que se encuentra almacenado en un
dispositivo direccionable; y donde sus registros poseen un campo que
denominaremos campo clave y que identifica inequívocamente a cada
registro. En los ficheros de acceso directo el campo clave es el
número del registro en el fichero. Así se establece una
correspondencia directa entre los valores del campo clave y las
direcciones lógicas en el soporte. Los registros se almacenan según
el orden de entrada y no quedan ordenados.
De esta forma en un Fichero de Acceso Directo nos referimos
a un registro por medio de su posición en este. Así, podremos
obtener el reg número 4 sin pasar antes por los demás.
+-----+------------+
| Reg | D A T O |
+-----+------------| Fíjese que los datos están
| 1 | LUIS | almacenados en el orden en el
| 2 | CARLOS | que han sido introducidos por el
| 3 | TERESA | usuario.
| 4 | JOAQUIN |
| 5 | INMA | Accedemos a los datos por medio
| 6 | JOSE | del valor de la posición del
+-----+------------+ registro.
La tabla anterior se denomina tabla de acceso. Esta tabla
relaciona de forma única el número del registro con el registro
correspondiente, así el reg número 2 corresponde al dato Carlos.
4.4.1 Ejemplo de I/O en Ficheros de Acceso Directo.
Las sentencias que manejan los ficheros de acceso directo
son las mismas, sólo que poseen el prefijo directo.
Ejemplo:
+-Algoritmo Contador_de_registros.
|
| Fichero de enteros F
| Variable entera x,contador
|
| Abrir directo (F)
| Iniciar lectura (F)
| contador = 0
| +-Mientras (NO fin(F)) hacer
| | Leer directo(F,x)
| | contador=contador+1
| +-Finmientras
| Cerrar(F)
|
| Escribir ("El fichero:";F;"posee:";contador;"reg.")
|
+-Final
4.5 Ficheros de Acceso Indexado.
Un Fichero de Acceso Indexado es aquel que se encuentra
almacenado en un dispositivo direccionable; y donde sus registros
poseen un campo que denominaremos campo clave principal y que
identifica inequívocamente a cada registro. La clave principal debe
ser aquel campo del registro estructurado que tenga siempre un valor
diferente a los ya introducidos, es decir, dentro del fichero
Indexado no puede haber dos registros con los campos clave principal
iguales.
Además del campo clave principal pueden existir otros campos
claves secundarios que realizan la misma tarea que el campo clave,
sin embargo, sus valores pueden repetirse. En los Ficheros de Acceso
Indexado el campo clave puede ser cualquiera de los campos de un
registro estructurado. Así se establece una correspondencia directa
entre los valores del campo clave y el propio registro al que
pertenece. Los registros se almacenan ordenados alfabéticamente por
el campo clave, esto nos facilita la búsqueda y listados ordenados
por los distintas claves.
Para cada campo clave, el fichero genera una tabla, donde
dicha clave aparece ordenada alfabéticamente y se relaciona con la
dirección de los datos.
De esta forma en un Fichero de Acceso Indexado nos referimos
a un registro por medio de alguna de las claves que posea el
fichero, tanto la principal como la secundaria. Es decir, leer el
registro cuya clave principal sea: 46.399.554, en este caso leería
el registro correspondiente a INMA. También podríamos haber dicho,
leer los registro cuya clave secundaria sea la Edad=16 y primero nos
leería el registro correspondiente a los datos de Luis y en la
siguiente petición de lectura los datos de Teresa. La diferencia
entre clave principal y secundaria, está en que la clave principal
es única (relacionando así inequívocamente al registro al que
pertenece) mientras que las claves principales puede ser iguales.
+------------+-------------------------------------+
| Clave | Clave Clave Clave |
| Principal | Secundaria Secundaria Secundaria |
+--------------------------------------------------+
+---------+------------+------------+-------------+--------+
| (Direc) | (D.N.I.) | (Nombre) | (Provincia) | (Edad) |
+---------|------------|------------|-------------|--------+
| 1 | 55.366.546 | LUIS | Las Palmas | 16 |
| 2 | 42.386.225 | CARLOS | Salamanca | 17 |
| 3 | 32.387.203 | TERESA | Oviedo | 16 |
| 4 | 46.399.554 | INMA | Palencia | 20 |
| 5 | 60.643.434 | JOAQUIN | Salamanca | 17 |
| 6 | 22.543.986 | JOSE | Las Palmas | 23 |
+---------+------------+------------+-------------+--------+
Como podemos observar, esto sería un ejemplo de un fichero
indexado.
Para cada campo clave, el fichero genera una tabla, donde
dicha clave aparece ordenada alfabéticamente y se relaciona con la
dirección de los datos. Así las tablas para la clave principal (DNI)
y la clave secundaria (Nombre) serían:
+------------+---------+ +------------+---------+
| (D.N.I.) | (Direc) | | (Nombre) | (Direc) |
+------------+---------| +------------+---------+
| 22.543.986 | 6 | | CARLOS | 2 |
| 32.387.203 | 3 | | INMA | 4 |
| 42.386.225 | 2 | | JOAQUIN | 5 |
| 46.399.554 | 4 | | JOSE | 6 |
| 55.366.546 | 1 | | LUIS | 1 |
| 60.643.434 | 6 | | TERESA | 3 |
+------------+---------+ +------------+---------+
+--------------------------+ +---------------------------+
| Tabla de Ac. Clave Princ.| | Tabla de Ac. Clave Secund.|
+--------------------------+ +---------------------------+
Obsérvese como ambas tablas aparecen ordenadas
alfabéticamente (o de menor a mayor en el caso del DNI). Como ya
dijimos, esto nos da grandes facilidades a la hora de realizar
búsquedas y/o listados ordenados.
4.5.1 Ejemplo de I/O en Ficheros de Acceso Indexado.
Pasemos a ver un ejemplo de como utilizar ficheros
indexados, pero antes veamos las sentencias básicas que
utilizaremos.
- Abrir indexado (variable,KEY=...)
Esta sentencia abre un fichero para el acceso indexado.
Donde la variable contiene el nombre del fichero a abrir y en 'KEY='
ponemos los campos claves separados por comas, comenzando por el
campo clave principal.
- Cerrar (variable)
Esta sentencia cierra un fichero donde la variable contiene
el nombre del fichero a cerrar.
- Leer/Escribir/Reescribir (variable1,KEY=,variable2)
Esta sentencia permite la lectura o re/escritura de los
datos por medio de un campo clave (principal o secundaria) que
debemos poner después de 'KEY='. El contenido será almacenado o
mandado por la variable2 en un fichero de nombre, el determinado en
la variable1.
- Iniciar operaciones de lectura y/o escritura en (variable)
Esta sentencia debe incluirse después de abrir un fichero y
determina prácticamente el tipo de acceso que vamos a realizar, es
decir, si abrimos el fichero para leer y/o escribir.
- NO fin (variable)
Esta función devuelve el valor lógico 'true' si no se ha
encontrado el final del fichero; y devuelve el valor lógico 'false'
si se ha encontrado el final del fichero.
- Error (variable)
Esta función devuelve el código del error producido al
realizar cualquier operación anterior. Por defecto, la función
devuelve un cero cuando no se ha producido ningún error.
Las sentencias que manejan los ficheros de acceso Indexado
son las mismas que hemos utilizado en los ficheros secuenciales,
sólo que poseen el prefijo Indexado y en las operaciones de lectura
y/o escrituras hay que indicar la clave ('KEY=').
Ejemplo:
+-Algoritmo Buscar_Persona.
|
| +-Registro estructurado datos_personales
| | Variable cadena dni
| | Variable cadena nombre
| | Variable cadena tlf
| | Variable cadena provincia
| +-Finregistro
|
| Fichero de datos_personales F
| Variable cadena documento
| Variable de datos_personales dato
|
| Escribir "Indique el DNI de la persona a buscar"
| Leer documento
|
| Abrir indexado (F,KEY=dni,nombre)
| Iniciar lectura (F)
|
| Leer (F,KEY=documento,dato)
| +-Si error(F)<>0 entonces
| | Escribir "Ese registro no existe."
| +-Sino
| | Escribir " DNI: ";dato.dni
| | Escribir " Nombre: ";dato.nombre
| | Escribir " Tlf: ";dato.tlf
| | Escribir "Provincia: ";dato.provincia
| +-Finsi
|
| Cerrar (F)
+-Final
4.6 Función de Hashing.
Muchas veces surge el caso del que el fichero es tan grande
que la tabla no puede mantener una ordenación eficaz debido a que
cuando introducimos un nuevo dato debe hacerse un espacio en la
misma para albergar a éste. Es por ello que recurrimos al "Hashing".
El "Hashing" consiste simplemente en relacionar la clave
principal con la dirección por medio de una fórmula matemática. Así,
antes de introducir datos se crean unos espacios para albergar las
futuras modificaciones y adiciones de datos. Este método crea una
serie de conjuntos llamados "Buckets". A cada Bucket le corresponde
un número que será el que devuelva la fórmula matemática. A su vez
los Buckets poseen un número que determina la cantidad máxima de
claves que pueden almacenarse en él.
De esta manera cuando vamos a buscar el dato "Manolo" el
Hashing nos determina la posición del conjunto (Buckets). En ese
conjunto habrá otra serie de datos a los cuales les corresponde el
mismo valor de la función Hashing. La búsqueda ahora se hará de
forma secuencial a lo largo del Bucket.
Veamos un ejemplo:
Bucket Clave Prin. Claves Secundarias
+-----+------------+----------------------+
| | Manolo | . . . |
| +------------+----------------------+
| 35 | Manuel | . . . | Al número 104
+-----+------------+----------------------+ se le denomina
+--| 104 | Manuela | . . . | puntero de
| +-----+------------+----------------------+ desbordamiento
| | | Natalia | . . . |
| | +------------+----------------------+
| | 36 | Naranjo | . . . |
| | +------------+----------------------+
| | | Noelia | . . . |
| +-----+------------+----------------------+
| .
| .
| .
| +-----+------------+----------------------+
| | | Mark | . . . |
| | +------------+----------------------+
+->| 104 | Miguel | . . . |
| +------------+----------------------+
| | María | . . . |
+-----+------------+----------------------+
4.6.1 Gestión de las colisiones.
En este método parecen una serie de conflictos cuando las
claves son muy parecidas, como podemos observar para claves casi
idénticas, el Hashing nos devuelve el mismo Bucket. Esto implica que
el Bucket puede llenarse de datos; cuando esto ocurre la solución
está en un puntero que existe en cada Bucket que determina el salto
a otro Bucket. Así, cuando se llena el Bucket número 35, existe un
salto de éste al número 104 (otro Bucket) que posee datos del mismo
tipo, que también puede rebosarse y apuntar a otro Bucket secundario
y así sucesivamente.
Ahora es cuando surgen los problemas. Cuando un dato se
borra de un Bucket hay que reorganizar la información para no dejar
espacios en blanco dentro de la tabla. Esto se realiza por medio de
un empaquetamiento Packed. Sin embargo cuando se va a realizar
muchas modificaciones y/o borrados y el fichero es muy grande, es
aconsejable hacer una actualización de los datos del fichero.
4.7 Esquema Básico de los tres tipos de Organización.
* Fichero de Acceso Secuencial:
- Almacenamiento en dispositivo secuencial o direccionable.
- No existe campos claves que relacione a algún registro.
- Los datos están almacenados en el orden en el que han sido
introducidos.
- El acceso a los registros es únicamente secuencial.
* Fichero de Acceso Directo:
- Almacenamiento en dispositivo direccionable.
- Existe en los registros un campo denominado campo clave
que hace referencia inequívoca a dicho registro a través del
número de registro.
- Los datos están almacenados en el orden en el que han sido
introducidos.
- El acceso a los registros puede ser tanto aleatorio a
través del campo clave como secuencial.
* Fichero de Acceso Indexado:
- Almacenamiento en dispositivo direccionable.
- Existe en los registros un campo denominado campo clave
principal y campo clave secundario, que hacen referencia
inequívoca a dicho registro.
- Los datos están almacenados en el orden alfabético por el
campo clave.
- El acceso a los registros puede ser tanto aleatorio a
través del campo clave como secuencial.
- El acceso Indexado-Secuencial permite el acceso como si se
tratara de un fichero secuencial, sin embargo, los datos no
saldrán en el orden en el que fueron introducidos sino en
orden alfabético por el campo que estamos leyendo.