Ingeniero Técnico en Informática de Sistemas
Ficheros en los Lenguajes de Programación
TEMA 1
1. INTRODUCCIÓN
Los datos con los que trabajamos normalmente en informática son procesados y manipulados de forma directa en lo que denominamos normalmente como Memoria Principal. Esto repercute en una doble limitación a la hora de tratar la información correspondiente :
Por ser limitada la memoria principal, esto implica que la capacidad de almacenamiento queda también limitada o restringida a la capacidad propia de cada memoria principal que puede ser de diferente tamaño según el ordenador y sus características. Por ello deberemos de recurrir a otros dispositivos de almacenamiento de datos o de almacenamiento masivo de información, como la denominada Memoria Auxiliar.
Todos los datos que quedan almacenados en la memoria principal, podemos decir que tienen un corto o breve período de vida que variará siempre en función del tiempo que dure o tarde en ejecutarse el programa en cuestión. Una vez que este programa finaliza su ejecución, sus datos correspondientes se pierden de forma irremediable y para siempre si antes no se han almacenado en un dispositivo o periférico de tipo externo como podría ser por ejemplo un disco de almacenamiento.
El uso de ficheros nos va a servir de gran ayuda a la hora de estructurar adecuadamente toda la información, y además nos facilitará el manejo de grandes volúmenes de datos. Los ficheros nos permiten acceder a esa creciente avalancha de información de una forma rápida.
Cualquier aplicación implica la generación y uso de una determinada información. Con algunas excepciones la entrada a la aplicación se hace utilizando archivos y casi en todas las aplicaciones, la salida se guarda en archivos para almacenamiento a largo plazo y para posteriores accesos por parte del usuario y de otros programas.
TEMA 2
2. CONCEPTOS Y DEFINICIONES
FICHERO
Un fichero es un conjunto de datos estructurados que pueden estar almacenados en un soporte de datos de forma que puedan ser tratados o utilizados de forma individual o global. Cada fichero se tiene que identificar con un nombre. Los elementos que forman un fichero se llaman registros y dichos registros se definen como la unidad mínima de información completa de un fichero.
Existen dos modelos de ficheros:
Fichero Lógico:
Los crea el programador agrupando un conjunto de datos con características comunes (nombres, apellidos, dirección, teléfono... etc. ).
Fichero Físico:
Es una determinada cantidad de información que el sistema operativo es capaz de tratar como una sola unidad.
TIPOS DE FICHERO
SEGÚN SU UTILIZACIÓN
Permanentes o fijos:
Constantes:
Contienen información fija y necesaria para el óptimo funcionamiento y rendimiento de la aplicación e información con un bajo índice de variación en el tiempo.
Por ejemplo un fichero de códigos postales en el cual se pueden relacionar códigos postales con una serie de diversas poblaciones y distritos. Contienen tablas y funciones.
Históricos :
Contienen información acumulada a lo largo del tiempo sobre las actualizaciones sufridas en los ficheros maestros y constantes. Los hacen los usuarios para las estadísticas. Por ejemplo el inventario al final de año de las existencias de un almacén.
Maestros :
Ficheros maestros llamados también ficheros de situación. Están encargados de mantener de forma constante y actualizados los campos cuya información es variable. Estos ficheros se modifican constantemente. Por ejemplo un fichero de inventario con información sobre la cantidad de piezas existente en un almacén.
No permanentes o temporales:
Se borran y actualizan a los ficheros fijos maestros.
Fichero de movimientos:
Este tipo de ficheros suele contener la información necesaria para la actualización de los ficheros maestros. Contienen las últimas modificaciones que hay que añadir al fichero maestro. La información se obtiene de los resultados obtenidos en operaciones realizadas y que posteriormente será utilizada para actualizar los campos que tienen en común el fichero maestro y el fichero de movimiento.
La durabilidad o período de vida de este tipo de ficheros es muy corto, debido a que su función o utilidad finaliza al efectuarse la modificación o actualización de dichos datos (Campos) en el fichero maestro. Una vez realizada dicha operación el fichero de movimientos puede ser destruido o mantenido durante un tiempo limitado. Por ejemplo los datos de una cuenta bancaria.
Ficheros de maniobra o transitorios:
Son ficheros auxiliares creados durante la ejecución de programas o aplicaciones. El fin de estos ficheros es el de obtener cierta información que posteriormente será procesada para conseguir unos resultados esperados o calculados. Su período de vida es aún mas corto que el de los ficheros de movimiento o transición, pues son destruidos antes de que el programa o la aplicación correspondiente finalice su ejecución y el usuario no puede verlos.
Por ejemplo un fichero auxiliar que contiene la clasificación de un fichero de inventario para hacer un listado estadístico anual. Finalizado el proceso de listado, es destruido.
Ficheros de trabajo:
Este tipo de ficheros son creados por el sistema para crear los ficheros de maniobra o transitorios.
SEGÚN SU ORGANIZACIÓN:
Ficheros secuenciales:
Es aquel fichero cuyos registros pueden ser tratados en secuencia, unos datos detrás de otros. Después de haber leído un registro el dispositivo de lectura se posiciona al principio del siguiente registro.
Este tipo de ficheros son muy convenientes cuando tenemos que leer todos los datos del fichero. No podemos añadir datos a un fichero secuencial, se copia todo en un fichero nuevo.
Ficheros relativos:
La principal ventaja de estos archivos es la de permitir el acceso directo a un determinado registro sin tener que acceder de forma secuencial, sino utilizando una clave para ello. En este tipo de ficheros la clave es fundamental ya que se utilizan para obtener la posición relativa de cada registro dentro del fichero. Estos ficheros deben estar almacenados en un soporte de acceso directo, como un disco duro o un disquete.
Ficheros indexados secuenciales:
Mediante este tipo de ficheros podemos solucionar el problema de los ficheros secuenciales respecto a la actualización y acceso a un registro, haciéndolo de forma casi directa, así como la realización de altas y bajas.
Este tipo de ficheros tiene que estar almacenado en un soporte físico de acceso directo.
Todos los registros del fichero tendrán un campo clave para identificarlo de forma única, no pudiendo existir dos registros con el mismo campo clave. Será por este campo por el cual se graben en orden ascendente y se localicen los registros del fichero.
Ficheros indexados:
En este tipo de ficheros se abandonan los conceptos de secuencialidad y clave única. Se alcanza una flexibilidad utilizando una estructura que utiliza múltiples índices, uno para cada tipo de campo que pueda ser objeto de búsqueda. A los registros se accede solo a traves de los índices. Como resultado existe una restricción a la ubicación de los registros. Por ello al menos un índice contiene un puntero a cada registro y pueden utilizarse registros de longitud variable.
Se suelen utilizar dos tipos de índices:
Un índice exhaustivo, que contiene una entrada para cada registro del archivo principal. Este índice se organiza en sí mismo como un archivo secuencial, facilitando la búsqueda.
Otro índice parcial contiene entradas a los registros donde está el campo de interés. Al utilizar registros de longitud variable, algunos registros no contendrán todos los campos. Si añadimos un registro al archivo principal, todos los archivos de índice deben actualizarse.
TEMA 3
3. ESTRUCTURA DE REGISTROS
Existen dos tipos de registros:
Registro lógico:
Son estructuras de datos homogéneas que hacen referencia a una misma entidad o cosa. Esta estructura está dividida a su vez en unos elementos más pequeños a los cuales denominaremos Campos, estos podrán ser del mismo o diferente tipo. Podríamos considerar al registro como una unidad de tratamiento incluida dentro de un fichero.
Registro físico:
Un registro físico al que podemos llamar también bloque, es la cantidad de información que el sistema operativo puede transferir como unidad al realizar una operación de entrada y salida entre la memoria principal del ordenador y los periféricos o dispositivos de almacenamiento. El tamaño de un bloque o registro físico dependerá o variará en función de las características del ordenador.
DEFINICIONES :
Campo :
Llamaremos campo a cada uno de los elementos que constituyen un registro lógico, considerándolo como una unidad de tratamiento independiente dentro del mismo registro. Cada campo se caracteriza y se diferencia de los demás dentro de un registro por:
El tipo de dato que tiene asociado (numérico, alfanumérico, lógico, de tipo fecha, de campo memo,... etc. ).
El identificador o nombre a través del cual podemos referenciarle y acceder a su contenido (nombre, apellidos, dirección, fecha de nacimiento,... etc. ).
El tamaño del dato (20 bytes, 45 bytes,... etc.).
Subcampo :
Los campos de un registro, con frecuencia, se pueden subdividir en unidades de tratamiento con las mismas características que un campo. De esta forma podemos establecer cierta jerarquía entre los datos almacenados dentro de un fichero y más concretamente dentro de cada registro. Esta jerarquía deberá tenerse en cuenta a la hora de tratar o procesar la información que tenemos almacenada. Dentro de un subcampo puede haber mas subcampos.
Campo clave:
Para poder diferenciar a un registro de otro dentro de un fichero, se tiene que recurrir a una información que sea única. Esta información sólo nos la puede ofrecer el campo clave. Este campo solo se puede crear con independencia del resto de la información (campos) del registro o por defecto se puede utilizar un campo de los ya existentes y disponibles en la estructura de dicho registro. El objetivo es poder realizar a traves de él operaciones de búsqueda y clasificación. La definición de un campo clave en un fichero no es obligatoria, es decir, se puede carecer de ella o puede estar formada por varias definiciones de campos claves, en cuyo caso se establecerán diferentes categorías entre ellas, dando lugar a lo que denominaremos como clave principal y claves secundarias.
Bloqueo de registro o registro bloqueado:
Un registro puede constar de un número variable de registros lógicos, por tanto, suponiendo que utilizáramos como soporte de almacenamiento el disco, podríamos transferir varios registros lógicos de la memoria al disco y del disco a la memoria en una sola operación de entrada y salida. Este fenómeno recibe el nombre de bloqueo y el registro físico así formado se llama bloque.
Registro expandido:
Es justamente el concepto contrario del registro bloqueado, cuando el registro lógico ocupa varios bloques se le da la denominación de registro expandido.
Factor de bloqueo:
Con factor de bloqueo hacemos alusión al conjunto o número de registros lógicos que pueden entrar o estar contenidos en un bloque o registro físico.
Ejemplo :
210 97 Tamaño del registro lógico.
16
2 Factor de bloqueo.
Resto : Nº de bytes que sobran.
Tamaño del registro físico.
REGISTRO LÓGICO
NOMBRE APELLIDOS DIRECCIÓN EDAD
Tamaño : 97 bytes
REGISTRO FÍSICO O BLOQUE DE 210 Bytes
REGISTRO LÓGICO 1 REGISTRO LÓGICO 2 ?
Factor de bloqueo=2 Espacio sobrante=16 bytes
Estructura de registros :
FICHERO
1 2 3 4 5 6 7 8 9 10 11 12
REGISTRO 7
COD_ALUMNO NOMBRE APELLIDOS FECHA_NAC
CAMPO FECHA_NAC
DIA MES AÑO
SUBCAMPO DIA
TEMA 4
CLASIFICACIÓN DE REGISTROS
Formas de gestión en varios
sistemas.
Registros de longitud fija.
Registros de longitud variable.
Un registro está constituido por campos. Estos pueden ser de longitud fija o variable e incluso existir un número distinto de campos en cada uno de los registros.
REGISTROS DE LONGITUD FIJA:
Los registros tienen todos el mismo tamaño.
Existen cuatro tipos o formas de diseño.
Con igual número de campos y la misma longitud. No es necesario definir ni el principio ni el final.
Ejemplo :
Tamaño :
Registro 30
campo 1 8 Se definen al principio del programa
campo 2 12
campo 3 10
2. Con igual número de campos pero distinta longitud, cambia la longitud. Tenemos que expresar la longitud de cada campo.
Ejemplo :
4 campo 6 campo 20 campo
Longitud del campo
Otro ejemplo :
TIPO A : A 4 16 10 =30 TIPO B : B 8 12 10 =30
campo 1=4 campo 1=8
campo 2=16 campo 2= 12
campo 3=10 campo 3=10
Poniendo al principio del registro el tamaño de los tres campos, será más rápido que el anterior porque mira los tres campos de una sola vez.
Cuando se tiene un número de campos igual en ambos registros, pero estos son de distinta longitud de campo en el mismo o diferentes registros.
Ejemplo :
REGISTRO Nº 1: CAMPO CAMPO CAMPO CAMPO
REGISTRO Nº 2: CAMPO CAMPO CAMPO CAMPO
Con distinto número de campos y distinta longitud:
1º) En primera posición se pone el número de campos, y antes de cada campo se pone su tamaño.
Ejemplo :
4 2 CAMPO 4 CAMPO 3 CAMPO 7 CAMPO
Número de campos Tamaño del campo
2º) Se ponen todos los datos al principio.
Ejemplo :
7 , 2 , 4 , 3
Tamaño de los campos
3º) Definiendo los tipos ( A, B, C ).
Ejemplo :
TIPO A : A 8 9 13 =30 TIPO B : B 6 20 4 =30
campo 1=8 campo 1=6
campo 2=9 campo 2=20
campo 3=13 campo 3=4
Lo normal es que los registros utilizados sean de longitud fija.
4.2 REGISTROS DE LONGITUD FIJA :
Ejemplos :
Mismo número de campos por registro e igual longitud de los campos en el mismo y distintos registros.
Registro 1 A B C D E F G H I J K L M
Registro 2 A B C D E F G H I J K L M
Igual número de campos por registro, y distinta longitud de cada campo del mismo registro e idéntica longitud del mismo campo en distintos registros.
Registro 1 A B C D E F G
Registro 2 A B C D E F G
Igual número de campos por registro, y distinta longitud de campos en el mismo y diferentes registros.
Registro 1 A B C D .................................. N
Registro 2 A B C D ........................ N
Registro 3 A B C D .................................. N
Diferente número de campos por registro y distinta longitud de campo en el mismo y diferentes registros.
Registro 1 A B C D E
Registro 2 A B C D
Registro 3 A B C D E F G H
4.3 REGISTROS DE LONGITUD VARIABLE :
El tamaño total del registro es variable ( longitud indefinida o variable). En este tipo de registros es necesario establecer desde el programa un tratamiento para diferenciar el comienzo y fin de cada campo y cada registro.
Existen tres tipos o formas de diseño :
1º) Ponemos al principio la longitud del registro y en cada campo la longitud del campo.
Ejemplo :
89 12 CAMPO 38 CAMPO 20 CAMPO 19 CAMPO
Tamaño total del registro Tamaño del campo
2º) Pondremos señales de final de campo y de registro.
Ejemplo :
CAMPO + CAMPO + CAMPO + CAMPO *
Señal de final de campo Señal de final de registro
3º) Definiremos tipos.
Ejemplo :
TIPO A : A 9 12 9 TIPO B : B 6 13 11
campo 1=9 campo 1=6
campo 2=12 campo 2=13
campo 3=9 campo 3=11
El resultado sería :
B CAMPO B CAMPO A CAMPO A CAMPO
Registros de longitud variable :
Son aquellos registros cuya longitud varía de un registro a otro.
Registro 1 A B C D E XXXXX
Registro 2 A B C D
Registro 3 A B C D E F G H XXXXXX
Registro 4 A B C D E F G H XXX
TEMA 5
5. OPERACIONES CON REGISTROS
Forma lógica
Pseudocódigo
FORMA LÓGICA :
Las dos operaciones esenciales que se pueden realizar con los registros son las siguientes :
LECTURA :
Esta operación implica el movimiento de información que va desde el fichero a la Memoria Central del ordenador. Esta información está contenida en un registro.
Para guardar la información del registro en la memoria central habrá que asignar unas variables. En la operación de lectura los nombres de las variables que están encargadas de almacenar los datos del registro leído se habrán asignado a los campos del mismo.
Los datos no desaparecen de la memoria auxiliar, sino que se copian en las variables antes mencionadas. En este momento ya podemos proceder a su uso para lo que queramos.
Si realizamos una nueva lectura, los datos del nuevo registro ocuparán el lugar del anterior sustituyéndolos. Solo podemos disponer de un registro en cada instante del proceso.
Cuando el fichero se acaba, el sistema detecta que lo que ha leído no es un registro, a esto se le llama marca de fin de fichero.
Un fichero de entrada es aquel que se utiliza para hacer operaciones de lectura, el flujo de información va desde el fichero a la memoria central.
ESCRITURA O GRABACIÓN :
Esta opción implica movimiento de información desde la memoria central hacia el fichero en cuestión. La información comprende al delas variables cuyos nombres coincidan con los campos definidos para un fichero
El fichero de salida es aquel que recibe la información de la memoria central y la escribe es sus registros.
Utilizando la lectura y escritura de registros podemos realizar una serie de operaciones, que son las siguientes:
Altas :
Consiste en la adición o inserción de uno o más registros en el fichero. Esta operación sólo será posible si el fichero ya existe.
Bajas :
Consiste en eliminar uno o varios registros del fichero. Esta operación requiere un primer proceso de lectura para la localización del registro que se pretende borrar.
Modificaciones :
Consiste en realizar un cambio total o parcial de uno o varios campos de los registros de un fichero. Esta operación requiere un primer proceso de lectura para la localización del registro que se desea modificar y un segundo proceso de escritura para la actualización de todo o parte del registro.
Consultas :
Esta operación nos permite acceder a uno o varios registros con la intención de visualizar el contenido total o parcial de sus campos en pantalla o impresora en forma de listados ordenados siguiendo ciertos criterios de clasificación establecidos por el usuario.
PSEUDOCÓDIGO :
FICHEROS SECUENCIALES :
Consultas :
Se supone :
Un fichero lógico llamado Fich.
Un registro llamado R_Fich.
La condición establecida campo_n = valor introducido por teclado.
El fichero Fich está asignado a un fichero físico y abierto para lectura.
a) Consulta en un fichero secuencial desordenado :
Búsqueda de un registro :
INICIO
Abrir Fich de lectura
Leer valor
sw=0
Mientras no FF (Fich) y sw=0 hacer
leer R_Fich de Fich
Si campo_n = valor entonces
sw=1
Finsi
Finmientras
Si sw=1 entonces
escribir R_Fich
sino
escribir “ No encontrado “
Finsi
Cerrar Fich
Fin
b) Consulta en un fichero secuencial ordenado :
Búsqueda de un registro :
INICIO
Abrir Fich de lectura
Leer valor
sw = 0
Mientras no FF (Fich) hacer
Leer R_Fich de Fich
Si campo_n >= valor
sw = 1
Finsi
Finmientras
Si sw = 1 y campo_n = valor entonces
Escribir R_Fich
Sino
Escribir “ No encontrado “
Finsi
Cerrar Fich
Fin
Búsqueda de todos los registros :
INICIO
Abrir Fich de lectura
Leer valor
sw = 0
Encontrado = F
Mientras no FF (Fich) y sw = 0 hacer
Leer R_Fich de Fich
Si campo_n > valor entonces
sw = 1
Sino
Si campo_n = valor entonces
Escribir R _Fich
Escribir Encontrado = V
Finsi
Finsi
Finmientras
Si Encontrado = F
Escribir “ No encontrado “
Finsi
Cerrar Fich
Fin
Actualización : (Altas, Bajas, y modificaciones )
Actualización por lotes :
Se actualiza un fichero origen ordenado por un campo clave con un lote de transacciones contenidas en un fichero de movimientos con la misma ordenación que el fichero origen, además contiene un campo que indica el tipo de movimientos ( alta, baja, o modificación ). Esto implica que la información que no sea baja o erronea pasa al fichero destino con los registros ordenados y actualizados. Los errores producidos en la actualización pueden ser enviados a una impresora o escritos en el soporte de almacenamiento para su posterior tratamiento.
Para la actualización, se van a utilizar cuatro ficheros :
Un fichero de origen ( Fich_origen )
Un fichero de movimientos ( Fich_mov )
Un fichero de destino ( Fich_destino )
Un fichero de errores ( Fich_errores )
INICIO
Variables :
clave_origen
clave_destino
registro_origen
registro_destino
registro_mov
registro_error
resto_destino
resto_mov
Abrir Fich_origen de lectura
Abrir Fich_mov de lectura
Abrir Fich_destino de escritura
Abrir Fich_errores de escritura
Fin_origen = 0
Fin_mov = 0
Procedimiento Leer_origen
Procedimiento Leer_mov
Mientras Fin_origen = 0 y Fin_mov = 0 hacer
Si clave_origen < clave_mov entonces
Procedimiento Copia
Procedimiento Leer_origen
Sino
Si clave_origen > clave_mov entonces
Procedimiento Alta
Procedimiento Leer_mov
Sino
Procedimiento Baja_modif
Procedimiento Leer_origen
Procedimiento Leer_mov
Finsi
Finsi
Finmientras
Mientras Fin_origen = 0 hacer
Procedimiento Copia
Procedimiento Leer_origen
Finmientras
Mientras Fin_mov = 0 hacer
Procedimiento Alta
Procedimiento Leer_mov
Finmientras
Cerrar Fich_origen, Fich_mov, Fich_destino, Fich_error
Fin
Procedimiento Alta :
INICIO
Según sea tipo_mov
`A´ :
clave_destino = clave_mov
resto_destino = resto_mov
Escribir registro_destino en Fich_destino
Otros :
registro_error = registro_mov
Escribir registro_error en Fich_error
Finsegún_sea
FinSegunSea
FIN
Procedimiento Leer_origen :
INICIO
Si FF ( Fich_origen ) entonces
Fin_origen = 0
Sino
Leer registro_origen de Fich_origen
Finsi
Fin
Procedimiento Leer_mov :
INICIO
Si FF ( Fich_mov ) entonces
Fin_mov = 0
Sino
Leer registro_mov de Fich_mov
Finsi
Fin
Procedimiento Baja_Modif :
INICIO
Según_sea Tipo-mov
`B´ :
** No se copia
`M´ :
** Se modifican los campos deseados
Escribir registro_destino en Fich_destino
Otros :
registro_error = registro_mov
Escribir registro_error en Fich_error
registro_destino = registro_orgen
Escribir registro_destino en Fich_destino
Finsegún_sea
Finsegunsea
FIN
Procedimiento Copia :
INICIO
registro_destino = registro_origen
Escribir registro_destino en Fich_destino
FIN
Actualización interactiva :
Consiste en actualizar un fichero introduciendo datos por teclado, produciremos altas. Bajas, y modificaciones de registros. Utilizaremos un fichero temporal para organizar el fichero cuando tengamos que hacer una baja o un borrado de registro. Las altas se producen en el lugar correspondiente, tendremos que utilizar un fichero temporal para reorganizar el fichero si este está ordenado, sino las altas se realizarán añadiendo registros al fichero. Los errores se presentan en pantalla cuando se producen.
Se utilizará un fichero llamado ( Fichero ) y un fichero temporal llamado ( Temp )
INICIO
Variables :
vclave
vale_clave
verif_clave
clave_registro
resto_registro
Repetir
Escribir “ 1. Alta
Baja
3. Modificación “
Escribir “ Seleccionar operación “
Leer operación
Según_sea operación
1 : Procedimiento Alta
2 : Procedimiento Baja
3 : Procedimiento Modificación
Finsegún_sea
Mientras operación > 0 y operación < 4 hacer
Cerrar Fichero
Fin
Procedimiento Alta :
INICIO
Escribir “ Introducir clave para alta “
Leer vclave
Vale_clave = Verif_clave ( vclave )
Cerrar Fichero
Si vale_clave = V entonces
Escribir “ Clave existente. No hay alta “
Sino
Abrir Fichero para añadir
clave_registro = vclave
Leer resto_registro
Escribir registro en Fichero
Finsi
Fin
Procedimiento Baja :
INICIO
Escribir “ Introducir clave para baja “
Leer vclave
vale_clave = verif_clave ( vclave )
Cerrar fichero
Si vale_clave = F entonces
Escribir “ No existe clave para baja “
Sino
Escribir registro
Abrir Fichero para leer
Abrir Temp para escribir
Mientras no FF ( Fichero ) hacer
Leer registro de Fichero
Si clave_registro <> vclave entonces
Escribir en Temp
Finsi
Finmientras
Borrar_Fichero ( Fichero )
Renombrar_Fichero ( Temp, Fichero )
Finsi
Fin
Procedimiento Modificación :
INICIO
Escribir “ Introducir clave para modificar registro “
Leer vclave
vale_clave = veirf_clave ( vclave )
Si vale_clave = F entonces
Escribir “ No existe clave para modificar “
sino
Escribir registro
** Leer valores de campos del registro que se va a modificar.
Escribir registro de Fichero
Finsi
Fin
Procedimiento Verificar_clave ( clave)
INICIO
Abrir Fichero para lectura y escritura
sw = 0
Mientras no FF ( Fichero ) y sw = 0 hacer
Leer registro de Fichero
Si clave_registro = clave
sw = 1
Finsi
Finmientras
Si sw = 1 entonces
retorno V
Sino
retorno F
Finsi
Fin
FICHEROS SECUENCIALES INDEXADOS :
Actualización desde un fichero secuencial de movimientos (Proceso Batch ) :
Iremos actualizando en un fichero secuencial de movimientos, durante un período de tiempo las altas, bajas, y modificaciones producidas sobre el fichero secuencial indexado. El fichero maestro contendrá todos los mismos campos, y además un campo tipo de movimiento. Uno de los campos será un campo identificador o clave por el que se buscará el registro.
Ejemplo :
Tenemos los siguientes ficheros :
AR_COD AR_NOM AR_DIRE AR_EXIS FARTI
X(5) A(30) 9(6) 9(4)
MV_COD MV_MOV MV_PRE MV_EXIS MV_TIPO FMOVI
X(5) A(30) 9(6) 9(4) A(1)
ER_COD ER_NOM ER_PRE ER_EXIS ER_TIPO ER_MEN
X(5) A(30) 9(6) 9(4) A(1) A(30)
FERROR
INICIO
Variables :
FARTI : Fichero Secuencial indexado
RARTI
AR _COD :Alfanumérico, 5
AR_NOM :Alfabético, 30
AR_PRE :Numérico, 6
AR_EXIS :Numérico, 4
FMOVI : Fichero Secuencial
RMOVI
MV_COD :Alfanumérico, 5
MV_NOM : Alfabético, 30
MV_PRE : Numérico, 6
MV_EXIS : Numérico, 4
MV_TIPO : Alfabético, 1
FERROR :Fichero Secuencial
RERROR
ER :COD : Alfanumérico, 5
ER_NOM : Alfabético, 30
ER_PRE : Numérico,6
ER_EXIS : Numérico, 4
ER_TIPO : Alfabético, 1
ER_MEN : Alfabético, 30
Abrir de entrada y salida FARTI
Abrir de entrada FMOVI
Abrir de entrada FERROR
Leer FMOVI
Mientras no FF FMOVI hacer
Si MV_TIPO = “A” entonces
Procedimiento ALTA
Sino
Si MV_TIPO = “B” entonces
Procedimiento BAJA
Sino
Si MV_TIPO = “M” entonces
Procedimiento MODIFICACIONES
Sino
ER_MEN ! “Error de tipo en FMOVI” Procedimiento ERROR
Finsi
Finsi
Finsi
Finmientras
Cerrar Ficheros FARTI, FMOVI, FERROR
Fin
Procedimiento Alta :
INICIO
AR _COD ! MV_COD
AR _NOM ! MV_NOM
AR_PRE ! MV_PRE
AR_EXIS !MV_EXIS
Grabar Directa FARTI
Si error en grabación entonces
ER_MEN ! “Registro ya existente”
Procedimiento ERROR
Finsi
Fin
Procedimiento Baja :
INICIO
AR_COD ! MV_COD
Borrar Directa RARTI
Si error en borrado entonces
ER_MEN ! “ Registro no existente “
Procedimiento ERROR
Finsi
Fin
Procedimiento Error :
INICIO
ER_COD ! MV_COD
ER_NOM ! MV_NOM
ER_PRE ! MV_PRE
ER_EXIS ! MV_EXIS
ER_TIPO ! MV_TIPO
Grabar RERROR
Fin
Procedimiento Modificaciones :
INICIO
AR_COD ! MV_COD
Leer Directa FARTI
Si error de lectura entonces
ER_MEN ! “ No existe registro “
Procedimiento ERROR
Sino
Si MV_NOM <> “ Espacios “ entonces
AR_NOM ! MV_NOM
Finsi
Si MV_PRE <> 0 entonces
AR_PRE ! MV_PRE
Finsi
Si MV_EXIS <> 0 entonces
AR_EXIS ! MV_EXIS
Finsi
Regrabar Directa RARTI
Finsi
Fin
Actualización desde el teclado ( Proceso On Line ) :
Las altas ,bajas y modificaciones se realizan según van produciendose. Estos procesos se denominan “ Procesos On Line “. El ordenador hace las preguntas y el operador o usuario envía respuestas a traves de teclado.
Ejemplo :
PRINCIPAL
MENÚ
1-ALTAS
2-BAJAS
3-MODIFICACIONES
4-SALIR
ELIGE :
SI 1 ! Procedimiento ALTAS
SI 2 ! Procedimiento BAJAS
SI 3 ! Procedimiento MODIFICACIONES
SI 4 ! FIN
Algoritmo Actualización Indexada
INICIO
Fichero Indexado
OPCIÓN ( Para los procedimientos )
Clave
Abrir Fichero de entrada y salida
OPCIÓN ! “ S “
Mientras OPCIÓN <> “ S “ hacer
Escribe “ MENÚ DE ACTUALIZACIÓN “
Escribe
Escribe “ 1- ALTAS “
Escribe “ 2- BAJAS “
Escribe “ 3- MODIFICACIONES “
Escribe “ 4- FIN “
Escribe “ ELIGE OPCIÓN “
Acepta OPCIÓN
Si OPCIÓN = 1 entonces
Procedimiento ALTA
Sino
Si OPCIÓN = 2 entonces
Procedimiento BAJA
Sino
Si OPCIÓN = 3 entonces
Procedimiento MODIFICACIONES
Finsi
Finsi
Finsi
Finmientras
Fin
Procedimiento Altas
INICIO
Escribe “ Dime la clave “
Acepta CLAVE ( La clave evita tener que leer todos los campos )
Leer Directa FICHERO
Si existe ( Si existe registro con esa clave ) entonces
Escribe “ Registro ya existente “
Sino
Escribe “ Dime datos “
Acepta datos
REGISTRO ! datos
Grabar Directa registro
Finsi
Fin
Procedimiento Bajas :
INICIO
Escribe “ Dime la clave “
Acepta CLAVE
Leer Directa FICHERO
Si no existe entonces
Escribe “ No existe “
Sino
COMPROBACIÓN : Escribir todos los datos
Sino
dato ! REGISTRO
Escribe datos
Escribe “ Borrar SI o NO “
Acepta S
Si S = si entonces
Borrar Directa REGISTRO
Finsi
Finsi
Fin
Procedimiento Modificaciones :
INICIO
Acepta CLAVE
Leer Directa FICHERO
Si no existe entonces
Escribe “ No existe, error “
Sino
Escribe “ Dime datos “
Acepta datos
REGISTRO ! datos
Regrabar Directa registro
Finsi
Fin
FICHEROS RELATIVOS :
Tanto la actualizaciones “ Batch “ como “ On Line “ en un fichero directo se realizan igual que con los ficheros secuenciales indexados. La única diferencia radica en la forma en que el sistema localiza un registro.
Existen dos variantes de organización relativa, directa o indirecta.
Organización Directa :
Cuando las claves son numéricas los registros se ubican en direcciones de memoria de tipo numérico entero. Esto facilita establecer una correspondencia directa entre la clave y la dirección de memoria. Por ello la secuencia lógica de almacenamiento de los registros coinciden con la secuencia física de almacenamiento de los registros sobre el soporte utilizado.
El valor de la clave está en relación de la capacidad del soporte de almacenamiento. No se puede almacenar un registro cuya clave esté por encima de los límites del fichero. El hecho de existir mas de un registro con la misma clave será un error, a lo que denominaremos sinónimo o colisión.
Organización Aleatoria o Indirecta
En este caso la clave debe sufrir un proceso de conversión a un valor numérico entero. Por ello la secuencia lógica no coincide con la física.
Nunca podremos almacenar registros cuyas direcciones de almacenamiento están por encima de los límites físicos del fichero.
En este tipo de organización cada dirección puede tener mas de un registro asociado. Este hecho recibe el nombre de sinónimo o colisión.
TEMA 6
6.FICHEROS EN EL SISTEMA
OPERATIVO
6.1 Sistema Ms-Dos
6.2 Sistema Unix
6.3 Sistema OS/2
6.4 Sistema MVS
Los registros son la unidad lógica de acceso a los archivos, mientras que los bloques son la unidad de entrada y salida para el almacenamiento secundario. Para realizar entradas y salidas los registros deben organizarse en bloques.
Los bloques pueden ser de longitud fija o variable. En la mayoría de los sistemas los bloques son de longitud fija, esto simplifica la entrada y salida, la asignación de memoria intermedia ( Buffers ) en memoria principal y la organización de los bloques en memoria secundaria.
Cuanto mayor sea el bloque mas registros se pasarán en una operación de entrada y salida.
Si el archivo se procesa secuencialmente es una ventaja porque usando bloques mayores se reduce el número de operaciones de entrada y salida. Por otro lado si se accede aleatoriamente a los registros y no existe cercanía en las referencias el uso de bloques mayores redunda en una transferencia innecesaria de registros no usados. Pero si combinamos las operaciones secuenciales con la cercanía de referencias el tiempo de transferencia se reduce usando bloques mayores. La única barrera es que los bloques grandes necesitan buffers de entrada y salida mayores, dificultando su gestión.
Existen tres métodos de agrupación en bloques :
Bloques fijos :
Utilizan registros de longitud fija, en cada bloque guardaremos un número entero de registros. Al final de cada bloque puede haber espacio sin usar.
Bloques de longitud variable por tramos :
Utilizan registros de longitud variable agrupados en bloques sin espacio por usar. Algunos registros usarán dos bloques, indicando con un puntero el bloque siguiente.
Bloques de longitud variable sin tramos :
Utilizan registros de longitud variable, pero no se dividen en tramos. Existirá un espacio desperdiciado en los bloques debido a ello no se podrá aprovechar el resto del bloque si el siguiente registro es mayor que el espacio sin usar.
Los bloques de tamaño fijo es lo más común para archivos secuenciales con registros de longitud variable.
El sistema operativo o el sistema de gestión de archivos es responsable de la asignación de los bloques a archivos. En primer lugar tenemos que asignar el espacio de memoria secundaria a los archivos y en segundo lugar guardar información sobre el espacio disponible para asignar. Estos dos temas están relacionados.
En la asignación de archivos surgen cuestiones :
Al crear un archivo ¿ Asignaremos el máximo espacio que necesite ?
Una asignación previa requeriría que el tamaño de un archivo se declarase al crearlo. Sin embargo para muchas aplicaciones es muy difícil estimar el tamaño posible del archivo. En estos casos la inclinación de usuarios y programadores sería sobrestimar el tamaño del archivo. Pero esto es un derroche desde el punto de vista de la asignación de memoria secundaria. Por tanto las ventajas usando asignación dinámica se hacen notar al asignar espacio a los archivos en secciones a medida que se necesiten.
El espacio se asigna en forma de unidades contiguas llamadas “ secciones “. ¿ Qué tamaño de sección usaremos para asignar archivos ?
En un extremo podemos asignar una sección grande para guardar el archivo entero o asignar espacio de bloque en bloque. Tendremos que considerar cuatro aspectos importantes :
El espacio contiguo aumentará el rendimiento sobremanera al ejecutar un sistema orientado a transacciones.
Un gran número de secciones pequeñas aumentan el tamaño de las tablas para gestionar la información
c) Disponer de secciones de tamaño fijo ( bloques ) simplifica la reasignación del espacio.
Las secciones de tamaño variable o pequeñas de tamaño fijo minimiza la perdida de espacio.
Como resultado aparecen dos opciones principales :
Secciones contiguas variables y grandes :
El resultado es un rendimiento mejor. El tamaño variable evita la perdida y las tablas serán pequeñas. Pero el espacio será difícil de reutilizar.
Bloques :
Las secciones fijas y pequeñas dan mayor flexibilidad. Podemos necesitar tablas grandes. La contigüedad se abandona y los bloques se asignarán a medida que se necesiten.
¿ Qué tabla usaremos para guardar constancia de las secciones asignadas a un archivo ?
Dicha tabla se conoce como “ Tabla de asignación de archivos “ denominada ( FAT ).
Cualquier opción es compatible con la asignación previa o la dinámica. En el primer caso se asigna previamente a los archivos un grupo contiguo de bloques, lo cual limita la necesidad de una tabla de asignación de archivos, Solo necesita un puntero al primer bloque y el número de bloques asignados. En el segundo caso todas las secciones necesarias son asignadas de una vez. Esto significa que la tabla de asignación del archivo permanecerá con tamaño fijo.
Si las secciones son de tamaño variable tenemos que pensar en la fragmentación del espacio libre. Existen unas estrategias alternativas.
Primer hueco ( first fit ) :
Tomaremos el primer grupo de bloques contiguo sin usar, de tamaño suficiente
Mejor hueco ( best fit ) :
Elegiremos el grupo más pequeño sin usar que tenga tamaño suficiente
Hueco más cercano ( nearest fit ) :
Tomaremos el grupo sin usar de tamaño suficiente más cercano al asignado previamente al archivo, para aumentar así la cercanía.
MÉTODOS DE ASIGNACIÓN DE ARCHIVOS :
Existen tres métodos :
Asignación contigua :
Al crear el archivo se le asigna un único conjunto contiguo de bloques. Esta es una estrategia de asignación previa que emplea secciones de tamaño variable. La tabla de asignación de archivos necesita una entrada por cada archivo que nos muestre el bloque de comienzo y l longitud del archivo. Este tipo de asignación es la más conveniente para un archivo secuencial ya que se pueden traer múltiples bloques de una sola vez, para mejorar el rendimiento en los tratamientos secuenciales.
Surgen también problemas, como fragmentación externa. Deberemos declarar el tamaño del archivo en el momento de la creación.
Asignación encadenada :
La asignación se hace con bloques individuales. Cada bloque contiene un puntero al bloque siguiente de la cadena. La tabla de asignación de archivos de nuevo una sola entrada por cada archivo que muestre el bloque de comienzo y la longitud del archivo. Aunque la asignación previa puede ser posible, lo más común es utilizar bloques a medida que se necesitan. La elección del bloque es simple, ya que cualquier bloque puede añadirse a la cadena. No nos preocupará la fragmentación externa porque solo se necesita un bloque cada vez. Este tipo de organización física se ajusta mejor a los archivos secuenciales. Para poder seleccionar un bloque debemos recorrer la cadena hasta el bloque deseado. Una consecuencia, es que no tendrá cabida el principio de cercanía. Por ello necesitaremos accesos a parte diferentes el disco cuando queramos traer varios bloques de un archivo al mismo tiempo.
Asignación indexada :
La tabla de asignación de archivos contiene un índice separado de un nivel para cada archivo, este índice posee una entrada para cada sección asignada al archivo. Los índices no están almacenados físicamente como parte de la tabla de asignación de archivos. El índice del archivo se guarda en un bloque aparte y la entrada del archivo en la tabla de asignación apuntará a dicho bloque.
La asignación por bloques elimina la fragmentación externa, y la asignación por secciones de tamaño variable mejora la cercanía. Los archivos pueden concentrarse en zonas cercanas de cuando en cuando. La concentración reduce el tamaño del índice para secciones de tamaño variable, pero no en el caso de asignación por bloques.
La asignación indexada soporta el acceso secuencial y el acceso directo a los archivos, y por ello es la forma más popular de asignación de archivos.
SISTEMA MS-DOS :
La tarea más frecuente en MS-DOS es la gestión de ficheros. Los ficheros mas importantes son :
Autoexec.bat :
Es un archivo de proceso por lotes. Contiene los archivos ejecutables de aplicación de los programas o rutinas que queremos ejecutar al cargar el sistema, tiene que estar situado en el directorio raíz.
Config.sys :
Es un fichero del sistema. Controla el sistema incluyendo dispositivos, opciones y tareas de búsqueda.
Command.com :
Este fichero contiene los comandos internos de ejecución que podremos utilizar sin necesidad de cargarlos.
Las operaciones mas frecuentes con ficheros son las siguientes :
CREAR FICHEROS DE TEXTO:
En general en un fichero de texto podemos almacenar cualquier tipo de información compuesta de caracteres.
Copy con :
Este comando copia el texto introducido por teclado en el disco.
Formato : copy con c :\ nombre_fichero
A continuación insertaremos es texto.
Para terminar pulsaremos F6 o control-Z
COPIAR FICHEROS.
Copy :
Formato : copy origen :\ fichero1 destino :\ fichero2
Utilización de comodines :
Es posible copiar con una sola operación un grupo de ficheros que tengan en el nombre una parte común.
El caracter “ * “ representa cualquier conjunto de letras del nombre.
Ejemplo :
copy *.dat a :! Copia todos los ficheros de extensión “ .dat “en a :
El carácter “ ? “ sustituye a un solo caracter
Ejemplo :
copy fichero?.dat a :! Copia todos los ficheros con nombre “ fichero “ mas un último caracter con extensión “ .dat “ en a :
Duplicación de un fichero :
Se puede copiar un fichero en el mismo disco con otro nombre.
Ejemplo :
copy fichero1.dat fichero2.dat
El modificador /V detrás del comando copy verifica que la copia se efectue correctamente.
MOVER UN FICHERO.
Move :
Consiste en cambiar de posición u fichero. Por ello primero copia el fichero en el disco destino y luego lo borra en el origen.
Formato : move origen :\ fichero.ext destino :\
MOVER UN GRUPO DE FICHEROS :
Se moverán utilizando los comodines “ * “ y “ ? “ como anteriormente hemos descrito.
Ejemplo :
move a :\ *.dat c :\
COMPARAR FICHEROS.
fc o ( comp ) :
Podemos comparar ficheros para ver si son idénticos.
Formato : FC unidad :\ fichero.ext unidad :\ fichero2.ext
También se pueden utilizar comodines para comparar grupos de ficheros.
Ejemplo :
FC c :\ fichero?.ext c :\ fichero2?.ext
BORRAR FICHEROS.
Del :
Podemos borrar ficheros innecesarios utilizando este comando.
Borrar un fichero :
Formato : Del unidad :\ fichero.ext
Utilizando “ Erase “ marcamos el archivo como eliminado permitiendo que otro fichero pueda grabarse en el espacio que antes ocupaba aquel.
Borrar un grupo de ficheros :
Utilizaremos comodines.
Ejemplo :
Del a :\ *.dat ! Borrará todos los archivos con extensión “ .dat “ de la unidad marcada.
Borrar ficheros con confirmación :
Utilizando el parámetro /P se solicitará confirmación antes de borrar el fichero.
RENOMBRAR FICHEROS.
Ren (Rename) :
Permite asignar un nuevo nombre a un fichero.
Formato : Ren fichero1.ext fichero2.ext
RECUPERACIÓN DE FICHEROS BORRADOS.
Undelete :
Mientras no se escriba sobre el fichero borrado podemos recuperar los archivos borrados.
Formato : Undelete unidad :\ fichero.ext
Si no especificamos ningún archivo, undelete recupera todos los archivos borrados.
Podemos utilizar comodines :
Ejemplo :
undelete *.dat ! Recupera todos los archivos con extensión “ .dat “
Con /ALL se recuperan todos los archivos sin pedir confirmación.
Con /List se mostrará una lista de ficheros borrados, pero no se recuperará ninguno.
SISTEMA UNIX :
El núcleo ( Kernel ) de UNIX contempla a todos los archivos como flujos de bytes. Cualquier estructura lógica interna será específica de la aplicación. Unix basándose en la estructura física de los archivos distingue tres tipos muy importantes de archivos de la siguiente manera :
Ordinarios :
Archivos que contienen información introducida por un usuario, programa de aplicación o programa de utilidad del sistema. Los archivos ordinarios se corresponden con los que la mayoría de los sistemas llaman simplemente archivos.
Directorio :
Contiene una lista de nombres de archivo y punteros a nodos-i ( nodos de información ) asociados. Los archivos de directorio son en realidad archivos ordinarios que tienen unos privilegios especiales de protección, ya que solo el sistema de archivos puede escribir en ellos, mientras que los programas de usuarios disponen de acceso para lectura.
Especiales :
Se usan para poder acceder a dispositivos periféricos, terminales, impresoras. Cada dispositivo de entrada y salida está asociado a un archivo especial.
Nodos-i :
Todos los archivos en Unix se administran por el sistema operativo por medio de nodos-i. Un nodo-i ( nodo índice ), es una estructura de control que contiene la información clave de un archivo necesaria para el sistema operativo. Se pueden asociar varios nombres de archivo a un mismo nodo-i , pero un nodo-i activo solo puede asociar a un único archivo, y ese es controlado por un solo nodo-i.
los atributos, permisos y cualquier otra información de control se almacena en el nodo-i.
En un sistema multiusuario existe la necesidad de permitir a los usuarios compartir archivos. Debido a esto surgen dos cuestiones : Los derechos de acceso y la gestión de los accesos simultáneos.
DERECHOS DE ACCESO :
Se debe ofrecer una herramienta flexible para permitir la compartición de archivos entre usuarios y un conjunto de opciones para controlar la manera de acceso a un archivo en particular, la lista muestra los derechos de acceso que pueden darse a un usuario particular para un archivo específico.
Ninguno :
El usuario no conoce el archivo y no puede acceder a él. No se permite al usuario leer el directorio que incluye el archivo.
Conocimiento :
El usuario sabe que el archivo existe y quien lo posee, puede solicitar derechos de acceso.
Ejecución :
El usuario puede cargar y ejecutar un programa pero no copiarlo.
Lectura :
El usuario puede leer, copiar y ejecutar el archivo.
Adición :
El usuario puede añadir datos al archivo pero no puede ni modificar ni borrarlo.
Actualización :
El usuario puede modificar, borrar y añadir datos al archivo.
Cambio de protección :
El usuario puede cambiar los derechos de acceso a otros usuarios
Borrado :
El usuario puede borrar el archivo del sistema.
Estos derechos constituyen una jerarquía, así si un usuario en particular adquiere el derecho de actualización, también adquiere el conocimiento, ejecución, lectura y adición del mismo.
ACCESOS SIMULTANEOS :
Cuando se otorga acceso para añadir o actualizar un archivo a mas de un usuario, el sistema operativo o el sistema de gestión de archivos debe cumplir una disciplina. Un método consiste en permitir a los usuarios bloquear el archivo entero cuando lo vaya a actualizar. Otro control es bloquear los registros individuales durante la actualización. Al diseñar la posibilidad de accesos compartidos, deben abordarse aspectos de exclusión mutua e interbloqueo.
ASIGNACIÓN DE ARCHIVOS :
Los archivos se asignan en bloques de forma dinámica, a medida que se necesiten. No se emplea asignación previa. Por tanto los bloques no tienen porqué estar contiguos necesariamente.
Se utiliza un método de indexación para seguir la pista de cada archivo, estando parte del índice almacenado en el índice de archivo.
El nodo-i incluye 39 bytes de información de direccionamiento, organizada como 13 direcciones o punteros de 3 bytes. Las 10 primeras apuntan a los 10 primeros bloques de datos del archivo. Si el archivo es mayor que 10 bloques, usaremos mas niveles de indexación de la forma siguiente :
La dirección undécima apunta a un bloque del disco que contiene la siguiente parte del índice. Este bloque se conoce como “ bloque de indexación simple “, contiene los punteros a los siguientes bloques de archivo.
Si el archivo contiene mas bloques, la dirección duodécima del nodo-i apunta a un bloque de indexación doble. Este contiene una lista de direcciones de bloques de indexación simple adicionales, y cada uno de estos contiene a su vez punteros a los bloques de archivo.
Si el archivo contiene aún mas bloques. La dirección decimotercera del nodo-i apunta a un bloque de indexación triple. Ese bloque apunta a bloques de indexación doble adicionales.
El número total de bloques de datos de un archivo depende de la capacidad de los bloques de tamaño fijo del sistema.
En Unix versión V, la longitud de un bloque es de 1Kb que a su vez albergara un total de 256 direcciones de bloques. Por ello el tamaño máximo de un archivo usando este esquema se aproximará a los 16Gb.
Las ventajas son las siguientes :
Los nodos-i son de tamaño fijo y pequeños, por lo que se pueden guardar en memoria principal durante períodos largos.
Se puede acceder a archivos pequeños con poca indexación, reduciendo el procesamiento y el tiempo de acceso al disco.
El tamaño máximo teórico de un archivo es suficientemente grande como para satisfacer a casi todas las aplicaciones.
SISTEMA OS/2 WARP :
Las ordenes en OS/2 se configuran de la misma manera que en MS-DOS. Los archivos tienen atributos, nombre y extensiones. OS/2 los trata como objetos en el escritorio.
OS/2 tiene dos sistemas de archivo : el sistema de archivos de tabla de archivos ( FAT ) y el sistema de archivos de alto rendimiento ( HPFS ).
El sistema HPFS sitúa el directorio raíz en el centro de búsqueda de la partición, esto mejora el tiempo de acceso.
El sistema FAT situa el directorio raíz al principio o final de la partición. La tabla guarda la posición de los datos en el disco fijo. Al solicitarse un archivo, el sistema operativo lee la tabla y posiciona el archivo en memoria.
HPFS asigna espacio contiguo a los archivos, esto hace que la
búsqueda de archivos sea más sencilla y rápida.
Con FAT los nombres tienen un máximo de 8 caracteres y una extensión de 3 caracteres.
Con HPFS los nombres tienen un máximo de 254 caracteres de tipo largo.
El sistema FAT no puede reconocer nombres de archivos creados por HPFS, pero si puede ocurrir al contrario.
Los ficheros pueden tener atributos extendidos. Como por ejemplo el nombre de usuario del creador del archivo. Los atributos extendidos se guardan en FAT n un archivo oculto con extensión “ . SF “.
Para HPFS, a aquellos archivos con espacios en el nombre hay que ponerle comillas antes y después para poder leerlos.
En un sistema FAT no importa si se utilizan mayúsculas o minúsculas en los nombres de archivo. El sistema operativo convierte a mayúsculas automáticamente. HPFS permite nombres de archivo tanto den mayúsculas como en minúsculas, siempre que no estén situados en el mismo directorio.
Para copiar archivos utilizaremos la orden Xcopy y sus parámetros :
/H : Copia archivos ocultos.
/T : Copia archivos de sistema.
/R : Copia archivos de solo-lectura.
/F : Copia atributos extendidos.
ARCHIVOS ESENCIALES EN OS/2 :
Config.sys :
Este fichero se encarga de controlar el sistema. Principalmente su tarea es gestionar los dispositivos, opciones y las tareas de búsqueda.
Startup.cmd :
Este archivo es similar al autoexec.bat. Es un archivo de procesos por lotes. Contiene los archivos ejecutables de aplicación de los programas que queramos ejecutar en el momento de cargar el sistema, el fichero debe de estar posicionado en el directorio raíz.
Swapper.dat :
Es un archivo de intercambio. OS/2 crea memoria virtual, de manera que todas las aplicaciones software piensan que tienen toda la memoria necesaria. OS/2 copia datos de la RAM en un archivo de intercambio llamado swapper.dat. Para utilizar este archivo tiene que estar activado. La activación se hace en el fichero config.sys. Swapper.dat puede crecer de tamaño de forma dinámica para satisfacer las necesidades de los procesos hasta un límite marcado en el fichero config.sys.
VISUALIZAR INFORMACIÓN DE ARCHIVO :
Deberemos pulsar con el botón derecho del ratón y solicitar vista de detalles. Esto cambia el formato de iconos en la carpeta por una información detallada de cada archivo. Esta operación es similar a la orden Dir de la línea de comandos.
Type :
Visualiza por pantalla el contenido de uno o varios ficheros.
Formato : Type fichero1 fichero2..........etc.
Esta orden acepta comodines.
Se puede redireccionar la salida del contenido de uno o más archivos a otro fichero destino.
Ejemplo :
Type fichero1 fichero2 > fichero_nuevo.
Copy :
Su utilización es igual a la vista en MS-DOS anteriormente.
Copia archivos entre directorios.
Copia archivos a la impresora.
Copia un archivo con otro nombre ( Duplicación de archivos )
Pero además combina archivos utilizando un signo mas “ + “ entre los nombres de archivo fuentes.
Puede cambiar atributos de hora y fecha introduciendo un signo mas “ + “ seguido de dos comas “ ,, “.
Ejemplo :
Copy MI_ARCH +,, ! Cambia la fecha y la hora del archivo.
Se pueden utilizar comodines :
Ejemplo :
Copy *.* +,, ! Cambia la fecha y la hora de todos los archivos.
El parámetro /F : Dice al sistema operativo que no copie un archivo en un directorio en el cual no se fueran a mantener los atributos extendidos del archivo.
OS/2 permite mover ficheros mediante el comando move ( Igual que en MS-DOS ). Pero solo se podrá hacer desde directorios de una misma unidad.
Los archivos por lotes se pueden ejecutar tanto en una sesión de OS/2 o de MS-DOS. Si estamos en una sesión de OS/2 se inicia automáticamente una sesión de DOS para ejecutar el archivo por lotes, esta sesión se cierra al terminar de ejecutarse el fichero.
ARCHIVOS POR LOTES Y DE ÓRDENES :
Un archivo de ordenes ( .CMD ) se ejecuta en una sesión de OS/2, un archivo por lotes ( .BAT ) se ejecuta en una sesión de DOS. Existen archivos .BAT que pueden ejecutarse en OS/2, solo tenemos que cambiar la extensión a .CMD.
ARCHIVOS DE ÓRDENES REXX Y CMD :
Ambos sólo se pueden ejecutar en sesiones de OS/2. Sin embargo, REXX es más potente y flexible, ya que realiza mas con menos esfuerzo. Al introducir un archivo de extensión .CMD el sistema operativo mira si en la primera línea del archivo aparece ( /* ), si es así el sistema operativo sabe que es un archivo por lotes REXX, ejecuta las instrucciones utilizando el intérprete REXX que es de donde viene la potencia adicional.
LISTADOS DE ARCHIVOS :
Para listar archivos y directorios utilizaremos el comando Dir y sus parámetros propios.
Ejemplos :
/ON : Clasifica por nombre alfabéticamente.
/O-N : Clasifica por nombre en orden alfabético inverso.
/OE : Clasifica por orden alfabético de la extensión.
/O-E : Clasifica por extensión.
/OD : Clasifica por fecha, con la fecha más temprana primero.
/O-D :Clasifica por fecha, con la fecha más tardía primero.
/OS : Clasifica por tamaño, con el más pequeño primero.
/O-S : Clasifica por tamaño, con el más grande primero.
/OG : Clasifica directorios, después archivos, en orden alfabético.
/O-G : Clasifica archivos, después directorios, en orden alfabético.
/A : Indica atributos.
DIR /A : Muestra todos los archivos del directorio incluyendo los ocultos y de sistema.
Ejemplo :
Dir /AH : Muestra todos los archivos ocultos.
/F : Visualiza los nombres de archivos completos, unidad, directorio, y nombre de archivo.
También podemos redireccionar una salida a un fichero :
Ejemplo : Dir c :\OS/2 > Listadir.
SISTEMA MVS/XA :
Es una nueva versión del MVS. ( XA ) quiere decir Arquitectura extendida.
Se diferencia del anterior en que el MVS tenía una limitación de 16Mb para direccionar, mientras que el MVS/XA dispone de 31 bits de direcciones lógicas y físicas. Por ello en el MVS/XA podemos direccionar 2Gb.
Los programas pueden seguir trabajando con direccionamientos de 24 o 32 bits respectivamente. Con todo ello aparece la memoria expandida situada en la caja de la CPU, es más lenta que la Memoria Principal pero más rápida que los discos. Su tamaño varía entre 4Kb y 2Gb
Existen varias organizaciones de archivos :
Secuencial :
El acceso es de acuerdo a un orden físico, un registro se almacena detrás de otro.
Secuencial indexado :
Los registros se ordenan mediante una clave, además mantiene índices de recuperación.
Directo al azar :
Los registros se organizan de cualquier forma y existe una clave para cada registro.
De partición :
Un archivo tiene múltiples subarchivos con un directorio, cada subarchivo pertenece a la partición.
ACCESOS A LOS REGISTROS :
Existen dos técnicas :
Técnicas de acceso por colas :
Se realiza un acceso secuencial y los registros se agrupan en anticipación de futuras peticiones.
Técnicas de acceso básico :
Podemos acceder a cualquier tipo registro cuando queramos.
Estas técnicas dan lugar a nuevos métodos ( BDAM, BSAM, BPAM,....ETC. ).
El método más interesante es el VSAM ( Método de acceso de almacenamiento virtual ), fue diseñado para proporcionar soporte al almacenamiento virtual.
Puede procesar tres tipos de datos :
Secuenciados por clave :
Cada registro tiene una clave y se cargan en secuencia de dicha clave.
Secuenciados por entrada :
Se cargan los registros de forma secuencial y el sistema devuelve una clave por cada registro, para realizar un acceso directo.
De registro relativo :
Se cargan los registros de acuerdo con un número de registro relativo.
Para localizar ficheros, se les dota de un nombre almacenado en un catálogo, en el cual se indica el volumen donde se encuentra el fichero. Una vez localizado se accede a un directorio denominado Tabla de contenidos del volumen ( VTOC ) para localizar el fichero.
Existen dos tipos o niveles de catálogos donde guardar los ficheros :
A estos catálogos se accede mediante una clave obtenida del nombre del fichero. El primer nivel se denomina maestro y el segundo está compuesto por catálogos de usuarios.
El catálogo maestro tiene dos tipos de entrada, por nombre y por alias.
Si entramos por nombre, se nos indica el volumen donde encontrarlo.
Si entramos por alias, en el catálogo maestro existe una referencia al catálogo de usuario donde ir a buscar el fichero
La VTOC se crea al iniciar el volumen ( disco ). Contiene una entrada para fichero. La asignación contigua es la utilizada para tratar estos ficheros.
Para evitar la fragmentación podemos utilizar el programa defrag compactando los huecos libres y una utilidad de usuario para definir el número de pistas iniciales y secundarias.
El espacio de grabación se selecciona entre los espacios disponibles utilizando el mejor ajuste.
TEMA 7
7. CLASIFICACIÓN DE FICHEROS
7.1 Ficheros permanentes
7.2 Ficheros Temporales o de Transacción
7.1 FICHEROS PERMANENTES
Son aquellos en los que sus registros permanecen inalterables (o casi inalterables) a través de los distintos procesos en los que intervienen. Así pues, un fichero que se procese realizando una sola operación de consulta se puede considerar como fichero permanente.
Dentro de estos ficheros, podemos hacer una triple subdivisión, atendiendo a la frecuencia de actualización.
FICHEROS CONSTANTES
Los datos de este tipo de ficheros no sufren habitualmente casi ninguna modificación, aunque a veces ocurra que forzosamente tengan que ser actualizados. En general, los registros que componen estos ficheros constan de una serie de campos. Unos perennes y otros susceptibles de ser modificados. Toda la información contenida en estos ficheros, es información de consulta y nunca contienen resultados. Un ejemplo claro de archivo maestro es un fichero con los datos de los empleados de una empresa, figurando en el fichero campos como nombre, DNI, número seguridad social... etc.
Hay algunos en los que incluso todo su contenido será fijo. Este tipo de ficheros son aquellos que contengan información inalterable, como tablas matemáticas, tablas periódicas... etc.
FICHEROS DE SITUACIÓN
Son los que tienen registros que se actualizan con más frecuencia. Contienen la situación actual de la información susceptible de sufrir frecuentes modificaciones o alteraciones.
Las modificaciones de la información contenida en los ficheros se hace en tiempo real, es decir, en el instante en que ocurren los cambios. La puesta al día de estos ficheros se realiza frecuentemente.
Se les llaman a veces “ficheros en línea” debido a que el proceso de actualización tiene que hacerse de forma instantánea. Estos ficheros reciben datos que le han sido enviados al ordenador a través de líneas de telecomunicación.
Un ejemplo de este tipo de ficheros es aquél en el que estén contenidas todas las cuentas corrientes de los clientes de una determinada entidad bancaria, sufriendo continuas modificaciones y siendo preciso que éstas se computen al instante. Otro ejemplo es un fichero de reservas de una empresa de ferrocarril, existencias de una almacén... etc.
FICHEROS HISTÓRICOS
Son aquellos cuyos registros contienen información referente a resultados de operaciones. Constituyen el resultado el tratamiento de la información para el ordenador.
En general se utilizan para confeccionar estadísticas y preparar informes. La información que utilizan pueden tomarla, bien de ficheros constantes o de ficheros de situación.
El contenido de estos ficheros puede ser de información ya resumida y directamente utilizable, o información detallada de la cual se tiene que confeccionar el resultado final.
Un ejemplo de este tipo de ficheros puede ser un fichero que contenga todas las incidencias ocurridas en un determinado período de tiempo en una empresa de ferrocarril, desvíos de trenes, salidas aplazadas, llegadas puntuales... etc. con el único fin de elaborar estadísticas.
7.2 FICHEROS TEMPORALES O DE MOVIMIENTO
Son los que contienen los registros resultantes del tratamiento de las transacciones o modificaciones. Van a servir en la mayoría de los casos para actualizar o consultar ficheros permanentes y para producir junto con los maestros la información final. La vida de estos ficheros es corta ya que contendrán información el tiempo que dure el proceso de actualización o consulta; cuando el proceso termina, no tiene ningún sentido mantenerlos activos. La desaparición puede ocurrir en el mismo momento de terminar la actualización del fichero maestro, o cuando haya otro nuevo fichero de movimientos que intervenga en el proceso.
Es el caso de un fichero de movimientos que modifique una determinada información de un fichero maestro. Por ejemplo, supongamos un fichero maestro con los datos de los empleados en una empresa. El fichero movimientos puede ser el que contenga todas las variaciones sufridas por esos empleados, tales como cambio de categoría, número de hijos, retención... etc.
TEMA8
8. FICHEROS SECUENCIALES
8.1 Organización
8.2 Tipos de acceso
8.3 Operaciones
8.4 Ejemplos
8.1 ORGANIZACIÓN
La organización de un fichero guarda una importante relación con el modo de acceso.
La organización es la forma particular de disponer los registros del mismo en el soporte de almacenamiento durante su creación.
Hay tres formas básicas de organizar un fichero:
- Organización Secuencial
Se caracteriza, fundamentalmente, por almacenar los registros físicamente contiguos, en el soporte auxiliar. Es decir, uno a continuación de otro y en la misma secuencia en que se introducen.
- Organización Secuencial Indexada
- Organización Directa o Relativa
Estos dos últimos tipos de organización se estudiarán aparte.
8.2 TIPOS DE ACCESO
Modo de acceso es la manera de acceder a los registros de un fichero para extraer (leer) información que pueda ser procesada posteriormente, o para grabar información nueva en el fichero.
Hay, fundamentalmente, dos formas de acceso:
- Acceso Secuencial
Se accede a los registros según su secuencia física, es decir, uno a continuación de otro, en el orden en que están escritos.
Dicho de otro modo, para acceder al registro S hay que pasar previamente por los S-1 registros anteriores.
- Acceso Directo
Permite el acceso a un registro determinado sin tener que pasar previamente por los registros precedentes.
La utilización de un método u otro, depende de cómo se organizó el fichero al crearse, del soporte donde está almacenado y de las necesidades específicas de cada programa.
En los ficheros con organización secuencial, el único modo de acceso posible es el secuencial.
Un ejemplo claro de la afirmación anterior sería asociar un fichero secuencial a una cassette de música. Cuando se graba en una cinta, las canciones se disponen una a continuación de otra. Si nuestra pletina no dispusiera de rebobinad, para poder escuchar una determinada canción sería necesario haber escuchado previamente las anteriores.
8.3 OPERACIONES
Las operaciones básicas se van a dividir en dos grupos. El primero incluirá aquellas que están relacionadas con los propios ficheros, y el segundo las relativas a sus registros considerados individualmente.
Las operaciones fundamentales que se pueden realizar sobre archivos son las siguientes:
CREACIÓN:
Para poder utilizar un archivo, éste debe haber sido creado previamente.
Crear un fichero significa introducir sus registros en el soporte de almacenamiento auxiliar elegido.
Al crear un archivo, se le asocia un nombre para poder referenciarlo posteriormente.
Cuando finaliza la creación de un fichero, el sistema graba en el mismo una marca final de fichero, cuya única utilidad es la de detectar, cuando se accede a dicho fichero de forma secuencial, si este ha terminado.
APERTURA:
Abrir un fichero quiere decir dejarlo dispuesto para ser utilizado.
Todos los archivos empleados en un programa deben ser abiertos, previamente a su uso.
CIERRE:
Cerrar un archivo significa dejarlo inaccesible para su uso.
Puesto que todos los archivos utilizados en un programa deben ser abiertos, en consecuencia, al finalizar el proceso, deben ser cerrados.
Sobre un archivo se pueden realizar otras operaciones como consulta, actualización clasificación, borrado.
8.4 TRATAMIENTOS
Las dos operaciones esenciales sobre registros son las siguientes:
LECTURA:
Una operación de lectura implica el traspaso de información desde el fichero a la memoria central del ordenador. La información que se traspasa es la contenida en un registro.
Como siempre, la única forma de guardar información en la memoria central es a través de variables. En una operación de lectura los nombres de las variables en que se reciben los datos del registro leído son los que se han asignado a los campos del mismo. En este movimiento de información, los datos transferidos no desaparecen de la memoria auxiliar sino que simplemente se copian en las variables correspondientes de la memoria central.
EJEMPLO:
Si hemos abierto previamente el fichero Agenda, que tiene la siguiente descripción:
NOM | DIR | TEL |
El nombre, la dirección y el teléfono del primer registro del fichero se guardarán en las variables Nom, Dir, Tel, respectivamente, de la memoria central del ordenador. A partir de este momento, se podrá operar con estas variables de la misma forma que hemos hecho hasta ahora: visualizarlas por pantalla, imprimirlas, etc.
Si efectúa una segunda lectura, el contenido del segundo registro pasará a las mismas variables de la memoria, sustituyendo sus anteriores valores. Por tanto, en cada instante del proceso sólo se dispone de la información del registro recién leído.
Si se sigue haciendo lecturas sucesivas sobre el fichero, llegará un momento en que éste se acabe; es decir ya no queden más registros por leer. Esta situación la detecta el sistema cuando, después de una operación de lectura, lo que se ha leído no es un registro de datos, sino lo que se conoce con el nombre de marca de fin de fichero. Por tanto, siempre que se ejecute una operación de lectura sobre un fichero secuencial, a continuación hay que preguntar si lo que se ha leído es la marca de fin de fichero o, por el contrario, un registro de datos para ejecutar las acciones pertinentes.
El termino de fichero de entrada se utiliza para caracterizar a aquellos ficheros que ya existen y sobre los cuales se van a realizar operaciones de lectura; es decir, el flujo de información va desde el fichero a la memoria central (la información entra en la memoria central). Esta cualidad del fichero debe indicarse en la operación de apertura del mismo.
ESCRITURA O GRABACIÓN:
Una operación de escritura implica el traspaso de información desde la memoria central del ordenador al fichero. La información que se traspasa es la contenida en las variables cuyos nombres coinciden con los campos definidos para un fichero.
EJEMPLO:
Tenemos un registro con la siguiente descripción:
NOM | DIR | TEL |
F.Agenda
Y se ha introducido desde el teclado un nombre, una dirección y un teléfono en las variables: Nom, Dir, Tel, respectivamente. El término fichero de salida se utiliza para referenciar a aquellos ficheros sobre los que se está escribiendo y, por lo tanto, el flujo de información va desde la memoria central al fichero (la información sale de la memoria central). Al igual que en los ficheros de entrada, dicha cualidad debe indicarse en la operación de apertura.
8.5 EJEMPLOS
Tenemos el siguiente fichero:
AL_NOM | AL_DIR | AL_EDAD | AL_NOT | AL_CUR | AL_ALT |
A(30) X(30) 9(2) 9(2) X(4) 9(3)
Realiza un ordinograma que imprima la nota media obtenida por los alumnos de 2º BUP y la edad media de los alumnos de COU
Algoritmo:
INICIO
Variables:
F.alum fichero secuencial
R.ALUM
AL_NOM : alfabético, 30
AL_DIR: alfanumérico,30
AL_EDAD : numérico,2
AL_NOT : numérico, 2
AL_CUR: alfanumérico, 4
AL_ALT: numérico, 3
C_DOS: numérico, 2
C_COU: numérico, 2
T_NOTA: numérico, 4
T_EDAD: numérico, 2
MED_NOT: numérico, 2
MED_EDAD: numérico, 2
Abrir de entrada F.alum
Leer F.alum
Mientras no F.F. hacer
Si AL_CUR =”2º BUP” Entonces
T_NOTA = T_NOTA + AL_NOT
C_DOS = C_DOS + 1
Sino
Si AL_CUR = “COU” Entonces
T_EDAD = TEDAD_ + AL_EDAD
C_COU = C_COU + 1
Finsi
Finsi
Leer F.alum
Finmientras
MED_NOT = T_NOTA/C_NOT
MED_EDAD= T.EDAD/C_COU
Imprime “Nota media” MED_NOT
Imprime “La nota media “EDAD_NOT
Imprime “La edad media” EDAD_MED
Cerrar F.alum
Fin.
Con el fichero del ejercicio anterior realizar un ordinograma para calcular e imprimir:
La estatura máxima de los alumnos de COU
La estatura mínima de los alumnos de 1º BUP
Algoritmo:
INICIO
Variables:
F.alum Fichero secuencial
RALUM:
AL_NOM: alfabético, 30
AL_DIR: alfanumérico, 30
AL_EDAD: numérico, 2
AL_NOT: numérico, 2
AL_CUR: alfanumérico, 4
AL_ALT: numérico, 3
AL_MAX: numérico, 3
AL_MIN: numérico, 3
Abrir de entrada F.alum
Leer F.alum
Mientras no F.F F.alum hacer
Si AL_CUR =”COU” entonces
ALT_MAX AL_ALT
Sino
Si AL_CUR = 1º BUP entonces
Si AL_ALT<ALT_MIN entonces
ALT_MIN AL_ALT
Finsi
Finsi
Finsi
Leer F.alum
Finmientras
IMPRIME “Altura máxima” ALT_MAX
IMPRIME “Altura mínima” ALT_MIN
Cerrar F.alum
Fin.
Utilizando el fichero anterior. Realizar un ordinograma para obtener dos ficheros secuenciales de salida, uno de alumnos aprobados y otro de alumnos suspensos, que tendrá la siguiente descripción:
AP_NOM | AP_DIR | AP_NOT | AP_CUR |
A(30) X(30) 9(2) X(4)
SU_NOM | SU_DIR | SU-NOT | SU_CUR |
A(30) X(30) 9(2) X(4)
INICIO
Variables:
F.alum fichero secuencial
R.alum
AL_NOM: Alfabético, 30
AL_DIR: Alfanumérico, 30
AL_EDAD: Numérico, 2
AL_NOT: Numérico, 2
AL_CUR: Alfanumérico,4
AL_ALT: Numérico, 3
F.aprova: fichero secuencial
R.aprova
AP_NOM: Alfabético,30
AP_DIR: Alfanumérico, 30
AP_NOT: Numérico, 2
AP_CUR: Alfanumérico,4
F_SUSP: fichero secuencial
R_F SUSP
SU_NOM:Alfabético,30
SU_DIR: Alfanumérico, 30
SU_NOT: Num, 2
SU_CUR: alfanumérico,4
Abrir de entrada: F.alum
Abrir de salida: F.alum, F.sup
Leer F.alum
Mientras no F.F F.alum hacer
Si AL_NOT <5 entonces
Procedimiento CAMPOS
Grabar R.SUP
Sino
Procedimiento CAMPOS II
Grabar R.APRO
Finsi
Finmientras
Fin
PROCEDIMIENTO CAMPOS
Inicio
SU_NOM AL_NOM
SU_DIR AL_DIR
SU_NOT SU_NOT
SU_CUR SU_CUR
Fin
POCEDIMIENTO CAMPOS II
Inicio:
AP_NOM AP_NOM
AP_DIR AP_DIR
AP_NOT AP_NOM
AP_CUR AP_CUR
Fin
Utilizando el fichero anterior, realizar un ordinograma para calcular e imprimir el nombre y la edad del primer alumno que, siendo de 2º BUP, con una nota no inferior a 7 y teniendo una estatura superior a 180 cm,sea el más joven.
ALGORITMO:
INICIO
Variables:
F.alum fichero secuencial
Ralum
AL_NOM: alfabético,30
AL_DIR: alfanumérico, 30
AL_EDAD: numérico, 2
AL_NOT: numérico,2
AL_CUR: alfanumérico,4
AL_ALT: numérico,3
C_DOS: numérico,2
C_COU: numérico, 4
T_NOTA: numérico, 4
T_EDAD: numérico,2
MED_NOT: numérico,2
MED_EDAD: numérico,2
AUX_NOM
MIN_EDAD
Abrir de entrada F.alum
Min edad=90
Leer F.alum
Mientras no F.F F.alum hacer
Si AL_CUR= “2º BUP” Entonces
Si AL_ALT>180 Entonces
Si AL_NOT>=7 Entonces
Si AL_EDAD <MIN_EDAD Entonces
MIN_EDAD AL_EDAD
AUX_NOM AL_NOM
Finsi
Finsi
Finsi
Finsi
Finmientras
FIN
Crear un fichero secuencial (FAGENDA), introduciendo el contenido de los campos de los registros desde el teclado. Su descripción es la siguiente:
AG_NOM | AG_DIR | AG_TEL |
A(30) X(30) X(7)
El proceso finalizará cuando se teclee un “*” en el campo nombre.
Variables utilizadas:
En este ejercicio no se necesitan variables ya que no hay que contar, acumular o guardar ningún campo del registro.
Proceso:
Del enunciado se deduce que será un proceso repetitivo cuya finalización (condición de salida) vendrá determinada por la introducción de un “*” en lugar de un nombre.
NOTA: Siempre que se efectúe una comparación con un literal alfabético o alfanumérico, éste debe ir entre comillas.
En un centro de enseñanza se tiene un fichero secuencial de alumnos, FALUM, cuyos registros se componen de los siguientes campos:
AL_NOM | AL_DIR | AL_EDAD | AL_NOT | AL_CUR | AL_ALT |
A(30) X(30) 9(2) 9(2) X(4) 9(3)
Siendo el campo AL_ALT la estatura en centímetros del alumno.
TEMA 9
9. FICHEROS RELATIVOS
9.1 Organización
9.2 Tipos de Acceso
9.3 Tablas de Gestión
9.4 Operaciones
9.5 Transformación de Claves
9.7 Método Hashing (o dispersión)
9.1. ORGANIZACION
Son ficheros a los que se puede acceder directamente a cada uno de sus registros, para ello se organiza la zona de fichero en dos partes:
-
Parte primaria o principal: Donde se graban todos los registros no
repetidos bien sean creación o actualización.
- Parte de sinónimos: Se graban los repetidos.
En todos los sistemas, la zona primaria se graba de la misma forma y en la de sinónimos cada zona es distinta en cada sistema.
Un fichero relativo se puede considerar como un conjunto de "casillas" del mismo tipo y tamaño, numeradas consecutivamente de 1 a N.
Son ficheros caracterizados porque:
a) El almacenamiento de los registros sobre el soporte seleccionado (memoria auxiliar) se realiza a través de un identificativo o clave que indica por una parte la posición del registro dentro del fichero y por otra la posición de memoria donde está ubicado.
b) La dirección de almacenamiento del registro dentro del soporte utilizado se obtiene siempre del identificativo o clave del propio registro, sabiendo que:
1. Si la clave no es numérica, es decir, alfabética o alfanumérica, se aplican algoritmos o fórmulas de transformación (matemáticas generalmente) para obtener valores enteros positivos que facilitan su posterior manejo y tratamiento.
2. Si la clave es numérica se aplica un algoritmo de transformación para obtener un rango de valores comprendido entre el intervalo de valores de las direcciones de memoria disponibles, estableciendo así una relación directa entre dirección lógica y dirección física.
El algoritmo de transformación que es aplicado a la clave debe cumplir tres condiciones:
a) Aprovechar al máximo el espacio disponible en memoria.
b) Establecer una correspondencia directa entre dirección lógica (clave) y dirección física (memoria).
c) Producir el menor número de registros que con diferentes claves generan idénticas direcciones de almacenamiento tras aplicar el algoritmo de transformación.
Los algoritmos de transformación utilizados en la conversión de claves reciben la denominación de Hashing.
Existen dos variantes de la organización relativa denominados directa y aleatoria o indirecta.
La diferencia entre estos, es que para grabar un fichero, cada registro tiene una clave en el propio registro de forma implícita que indica dónde hay que grabar ese registro, las claves son directas cuando no necesitan transformación para utilizarse e indirectas cuando hay que transformarlas.
ORGANIZACION DIRECTA
Este tipo de organización, se da en aquellos casos en los que las claves sean numéricas, estableciéndose una correspondencia directa entre dirección lógica y dirección física. Al ser la clave de tipo numérico, no surgen problemas, pues los registros se ubican en direcciones de memoria de tipo numérico entero, lo que facilita establecer una correspondencia directa entre la clave y la dirección de memoria, de todo ello, podemos deducir que la secuencia lógica de almacenamiento de los registros en el fichero coincide con la secuencia física de almacenamiento de los registros sobre el soporte utilizado.
El valor de la clave siempre está en relación con la capacidad máxima de soporte físico utilizado para el almacenamiento, por lo que nunca podemos almacenar un registro cuya clave esté por encima de los límites máximos del fichero.
Utilizando este tipo de organización, cada dirección sólo puede ser ocupada por un registro. El hecho de existir más de un registro con la misma clave es causa de error ya que ello supondría la posibilidad de almacenar en el fichero un registro repetido, lo cual no es posible en este tipo de organización. Este hecho recibe el nombre de sinónimo o colisión.
Las ventajas más destacables en este tipo de organización son:
a) Permite acceder a los datos de dos formas diferentes.
1. Directamente, mediante el identificativo o clave del fichero.
2. Secuencialmente, partiendo siempre del primer registro almacenado en el fichero.
b) Permite realizar operaciones de escritura/lectura simultáneamente.
c) Son muy rápidos en el tratamiento de registros individuales.
Los inconvenientes más destacables en este tipo de organización son:
a) Una consulta total del fichero, puede suponer un gran inconveniente, pues al realizar un acceso secuencial sobre los datos del fichero, estamos obligados a analizar posición por posición desde la primera hasta la última pudiendo ocurrir que algunas posiciones estén vacías, lo cual implica una considerable pérdida de tiempo, por lo que es necesario el empleo de técnicas avanzadas de programación para realizar lecturas secuenciales.
b) Deja gran cantidad de huecos (posiciones libres en memoria) dentro del fichero. Estos huecos surgen debido a los identificativos de los registros que se desean almacenar después de haber sido introducidos en el fichero indican posiciones de almacenamiento probablemente no contiguas, lo que implica un desaprovechamiento del soporte de almacenamiento o memoria auxiliar, respecto al número real de registros almacenados.
c) Se deben dar soluciones al problema de los sinónimos o colisiones.
ORGANIZACION ALEATORIA O INDIRECTA
Esta variante de la organización relativa se dan en aquellos casos en los que la clave debe sufrir un proceso de conversión que permita obtener un valor numérico entero facilitando así la correspondencia directa que se debe establecer entre la clave y la dirección de memoria. Este caso, la secuencia lógica de almacenamiento no coincide con la secuencia física.
El valor de la clave siempre debe estar en relación con la capacidad máxima del soporte físico utilizado para el almacenamiento de la información, por este motivo nunca podemos almacenar registros cuya dirección de almacenamiento esté por encima de los límites máximos del fichero y, si así ocurriese, resultaría que el algoritmo de almacenamiento no sería correcto.
En este tipo de organización, cada dirección puede ser ocupada por más de un registro, pues este hecho no es causa de error, ya que ello se debe a que el algoritmo de transformación que hemos aplicado al identificativo o clave (en este caso alfabética o alfanumérica) ha generado con distinto identificativos la misma posición de almacenamiento en memoria, lo cual sí es posible en esta variante de organización relativa. Este hecho recibe el nombre de sinónimo o colisión.
Las ventajas más destacables en este tipo de colisión son:
a) Permite un acceso inmediato a los registros haciendo únicamente referencia a su clave.
b) No requieren de procesos u operaciones de ordenación.
c) Este tipo de organización permite realizar operaciones de escritura/lectura a la vez.
d) Son muy rápidos en el tratamiento individual de los registros.
e) Permite acceder secuencialmente a los datos siempre que se desee.
Los inconvenientes más destacables en este tipo de organización son:
a) Las consultas completas del fichero pueden resultar excesivamente lentas.
b) De la misma forma que ocurría con la organización directa, este tipo de organización deja gran cantidad de hueco o espacios libres dentro del fichero.
c) Tanto el algoritmo para la transformación o conversión de las claves como el algoritmo necesario para el almacenamiento y tratamiento de sinónimos corren a cuenta del programador, siendo responsabilidad de este aplicar un método que deje el menor número de huecos libres y genere el menor número de sinónimos.
9.2 TIPOS DE ACCESO
Al igual que en los ficheros de organización secuencial indexada, en un fichero con organización directa pueden utilizarse fundamentalmente dos tipos de acceso: acceso secuencial y acceso directo. Algunos lenguajes admiten también el acceso dinámico.
ACCESO SECUENCIAL
Consiste en acceder, tengan o no contenido, a todas las posiciones del fichero desde la primera hasta la última.
Algunos lenguajes (COBOL por ejemplo), poseen rutinas para detectar si una "casilla" tiene contenido o es un "hueco" y saltarla en este caso. En otros lenguajes (como el BASIC), esta situación se debe controlar mediante programa.
ACCESO DIRECTO
Permite acceder a un determinado registro con sólo indicar su clave.
A todo fichero directo hay que asignarle una variable de memoria, externa por tanto al fichero, que guardará la posición del registro al que se desea acceder.
De igual forma que a los ficheros secuenciales indexados, después de cada una de las operaciones realizadas sobre un fichero relativo, hay que preguntar si se ha podido ejecutar la instrucción o no, para tomar las medidas oportunas en cada caso.
ACCESO DINÁMICO
Consiste en acceder directamente a una determinada posición y a partir de ella recorrer secuencialmente un grupo de registros.
En general el modo de acceso más utilizado para ficheros con este tipo de organización es el acceso directo.
Las operaciones que se pueden realizar con cualquier tipo de acceso son las mismas que para ficheros con organización secuencial indexada, la diferencia fundamental estriba en la forma en la que el sistema accede a un determinado registro:
- Si en la creación del fichero no se utilizó algoritmo de
transformación de claves, la clave de cada registro indicará
directamente la posición relativa del mismo.
- Si en la creación del fichero se utilizó un algoritmo, entonces a la clave del registro tratado se le aplicará el mismo algoritmo que en la creación, para obtener la posición relativa de dicho registro.
9.3 TABLAS DE GESTIÓN EN PARA ARCHIVOS
RELATIVOS EN “C”
Este programa pasa un fichero secuencial a uno DIRECTO, Los sinónimos de encuentran entre el registro 250 y 299.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <iostream.h>
#include <ctype.h>
void main(void)
{
int i,clave,aux;
char tecla;
struct secuencial
{
char nombre [50];
char apellido [50];
int cod;
}
struct directo
{
char nombre[50];
char apellido[50];
int cod;
char ocupado;
}
struct secuencial secu;
struct directo direc;
FILE *fs ,*fd;
clrscr();
/* Abrimos los ficheros */
if ((fs=fopen(“a:\\clase”, “rb”))==NULL)
{
puts(“Error de apertura (secuencial)”);
exit(1);
}
if ((fs=fopen(“a:\\clase”, “rb”))==NULL)
{
puts(“Error de apertura (secuencial)”);
exit(1);
}
/* introducimos los registros del secuencial en su posición del */
/* directo*/
fread(&secu,sizeof(struct secuencial),1,fs);
i=0;
/* la condición de salida es el fin del fichero secuencial*/
while (feof(fs)==0)
{
/* nos situamos donde le corresponde el registro según */
/* su código */
clave=(secu.cod%250)+1;
fseek(fd,clave*sizeof(struct directo),SEEK_SET);
fread(&direc,sizeof(struct directo),1,fd);
if(direc.ocupado==`s')
{
/*nos vamos a la zona de sinonomos y... */
/*recorremos para encontrar un sitio libre */
fseek(fd,250*seizeof(struct directo),SEEK_SET);
aux =-1;
do
{
aux++;
fread (&direc,sizeof(struct directo),1,fd);
}
while ((Feof(fd)==0&&(direc.ocupado==`s'));
/* comprobamos que el fichero no esté deteriorado*/
if(feof(fd))
{
puts(“\t FICHERO DETERIORADO DEBE
REORGANIZARSE ZONA DE SINONIMOS
LLENA”);
Exit(1);
}
/*retrocedemos un lugar para volver a la primera posición */
fseek(fd,(250+aux)*sizeof(struct directo), SEEK_CUR);
/*copiamos las estructuras y cambiamos el campo ocupado */
strcpy(direc.nombre, secu.nombre);
strcpy(direc.apellido,secu.apellido);
direc.cod=secu.cod;
direc.ocupado=`s';
/*grabamos el registro en el fichero indirecto */
fwrite(&direc,sizeof(struct directo),1,fd);
}/* fin del if (direc.ocupado==`s')
else
if(direc.ocupado==`n')
{
strcpy(direc.nombre, secu.nombre);
strcpy(direc.apellido, secu.apellido);
direc.cod=secu.cod;
direc.ocupado=`s';
fseek(fd,clave*sizeof8struct directo),SEEK_SET);
fwrite(&direc,sizeof(struct directo),1,fd);
}
else
puts (“error de campo(direc.ocupado)”);
}
fread(&secu,sizeof(struct secuencial),1,fs);
}
do
{
clrscr();
puts(“INTRODUZCA EL CODIGO DEL REGISTRO A
VISUALIZAR”);
/*el código debe estar entre 0 y 299 */
do
{
cin>>i;
if((i<0)&&(i>299))
puts(“EL NÚMERO DEBE SER SUPERIOR A 0
E INFERIRO A 300);
}
while ((i<0)&&)(i>299));
/*situamos el puntero en la posición del código */
clave=(i%250)+1;
fseek(fd,clave*sizeof(struct directo),SEEK_SET);
fread(&direc,sizeof(struct directo),1,fd);
/*comprobamos que el registro este exista */
if(direc.ocupado==`n')
{
puts(“NO EXISTE ESTE REGISTRO”);
getch();
}
else
{
if (direc.cod==i)
{
printf(“NOMBRE -> %s\n”, direc.nombre);
printf(“APELLIDO -> %s\n”, direc.apellido);
printf(“NUMERO -> %d\n”, direc.numero);
printf(“OCUPADO -> %c\n”, direc.ocupado);
}
else /* hay que buscarlo en la zona de sinónimos */
{
fseek (fd,250*sizeof(struct directo),SEEK_SET);
aux=-1;
do
{
aux++;
fread(&direc,sizeof(struct directo),1,fd);
}
while ((feof(fd)==0)&&(direc.cod!=i));
if (feof(fd))
{
puts (“\t FICHERO DETERIORADO
DEBE REORGANIZARSE ZOPNA
DE SINONIMOS”);
exit(1);
}
/*retrocedemos un lugar para volver a la posición del registro*/
fseek(fd,(aux+250)*sizeof(struct directo),SEEK_CUR);
fread(&direc,sizeof(struct directo),1,fd);
printf(“NOMBRE -> %s\n”, direc.nombre);
printf(“APELLIDO -> %s\n”, direc.apellido);
printf(“NUMERO -> %d\n”, direc.numero);
printf(“OCUPADO -> %c\n”, direc.ocupado);
} /* fin else if (direc.cod==1) */
}
/*preguntamos si queremos visualizar otro registro */
puts(“DESEA VER ALGUN REGISTRO (S/N)”);
tecla=getch();
}while (tolower(tecla)!=`n');
}
9.4 OPERACIONES
Seguidamente estudiaremos las diferentes operaciones que podemos realizar sobre ficheros con independencia del tipo de organización o acceso que hayamos seleccionado.
CREACIÓN
Para poder realizar cualquier operación sobre un fichero es necesario, que haya sido creado, previamente, almacenando sobre el soporte seleccionado la información requerida para su posterior tratamiento. Esto requiere que inicialmente se establezca la forma en la que la información almacenada en el fichero será procesada en un futuro, así como el tipo de organización y acceso que emplearemos para el manejo de dichos datos.
APERTURA
Para poder trabajar con un fichero, este debe estar abierto, permitiendo así el acceso a los datos, dando la posibilidad de realizar sobre ellos las operaciones de lectura y escritura necesarias. Como norma general, un fichero nunca deberá permanecer abierto más tiempo del estrictamente necesario entendiendo como tal el periodo de tiempo empleado para la realización de cualquier operación de lectura o escritura sobre él.
CIERRE
Una vez finalizado las operaciones efectuadas sobre el fichero, éste debe permanecer cerrado para limitar el acceso a los datos y evitar así un posible deterioro o pérdida de información.
ACTUALIZACIÓN
Esta operación permite tener actualizado el fichero mediante la escritura de nuevos registros y la eliminación o modificación de los ya existentes. Esta operación puede afectar a partes o la totalidad de los registros.
ORDENACIÓN O CLASIFICACIÓN
Esta operación permite establecer un orden entre los registros almacenados dentro del fichero. La ordenación puede ser ascendente o descendente.
COPIADO O DUPLICADO
Esta operación parte de un fichero origen y crea un nuevo fichero destino con la misma estructura y contenido que el primero. Dicha operación deja intacto el fichero original.
CONCATENACIÓN
Se parte de la existencia de dos ficheros con la misma estructura, de manera que la concatenación de ambos crea un tercer fichero de igual estructura y cuya información es la suma del contenido del primer fichero más el contenido del segundo. Dicha operación no afecta a los ficheros originales.
FUSIÓN O MEZCLA
Esta operación permite obtener de dos o más ficheros con la misma clasificación y estructura interna de sus datos, un nuevo fichero que contenga dos registros de todos los anteriores sin alterar la ordenación que éstos tenían establecida. Dicha operación no afecta a los ficheros que intervienen en el proceso de fusión.
INTERSECCIÓN
Consiste en crear un nuevo fichero partiendo de los registros comunes de dos o más ficheros con la misma estructura.
PARTICIÓN O ROTURA
Esta operación permite obtener varios ficheros de uno inicial en función de alguno de las características internas de sus campos.
COMPACTACIÓN O EMPAQUETAMIENTO
Esta operación permite la reorganización de los registros de un fichero eliminando los huecos libres intermedios existentes entre ellos, normalmente ocasionados por la eliminación de registros.
CONSULTA
A través de las consultas es posible acceder a dos registros del fichero y conocer el contenido de sus campos.
BORRADO DE INSTRUCCIÓN
Es la operación inversa a la creación de un fichero, y en consecuencia una vez efectuada dicha operación se pierde toda posibilidad de acceder a los datos previamente almacenados.
9.5 TRANSFORMACIÓN DE CLAVES
INTRODUCCIÓN
El identificativo o clave sirve para diferenciar unos registros de otros dentro de un mismo fichero. Este identificativo es un campo, subcampo, conjunto de campos o conjunto de subcampos que identifican a cada registro.
En general, los identificativos sirven para:
a) Introducir registros dentro del fichero recibiendo el nombre de identificativo de orden.
b) Localizar registros dentro de un fichero atendiendo a una determinada cualidad. En este caso le llamaremos identificativo de búsqueda.
Generalmente, el identificativo forma parte del registro, es decir, constituye información dentro del registro y actúa a la vez como identificativo de orden y como identificativo de búsqueda.
Los identificativos pueden ser de tres tipos:
- Numéricos.
- Alfabéticos.
- Alfanuméricos.
Los identificativos de tipo numérico se emplean principalmente en ficheros con organización relativa mientras que los alfabéticos y alfanuméricos se utilizan en los indexados, aunque los tres tipos pueden utilizarse en cualquiera de las organizaciones.
CONVERSIÓN DE IDENTIFICATIVOS EN FICHEROS RELATIVOS (DIRECTOS).
La utilización de métodos de cálculo de la dirección proporciona ventajas, aunque también presenta inconvenientes tales como son la producción de sinónimos.
Es el usuario o programador el que elegirá el algoritmo de direccionamiento y además será el que decida el lugar en el que deben almacenarse los registros.
A continuación se detallan una serie de técnicas de transformación de identificativos en direcciones físicas de almacenamiento. Para ello utilizaremos identificativos monocampo. El contenido de ellos podrá ser numérico, alfabético o alfanumérico.
Para que una transformación sea efectiva, es decir, para que un algoritmo de transformación sea válido, tiene que cumplir una serie de requisitos, tales como tener una tasa de relleno superior al 80-85%. La fórmula de la tasa de relleno es la siguiente:
Tasa de relleno =Número máximo de registros / 100
CONVERSIÓN DE IDENTIFICATIVOS NUMÉRICOS
Direccionamiento directo
El direccionamiento directo es más utilizado siempre y cuando el número total de registros a almacenar en el fichero no sea demasiado grande y los identificativos de los registros tampoco sean muy grandes. La principal característica de este método es la de no tener que realzar ningún cálculo para averiguar la dirección y la tasa de relleno (ocupación del soporte) será el 100%.
Como su nombre sugiere, el identificativo será el que indique la dirección física de almacenamiento sin necesidad de realizar ninguna transformación. Esto implica directamente que este tipo de direccionamiento no produce colisiones, es decir, no produce sinónimos. Es imposible que dos registros con el mismo identificativo estén residentes a la vez en el fichero.
El valor del identificativo ha de ser necesariamente numérico, ya que las direcciones de almacenamiento tienen que venir dadas por números. Además, el contenido de este identificativo no puede ser demasiado grande, ya que al indicar directamente la dirección física, que además coincide con la dirección lógica, ésta, necesariamente, tiene que estar dentro de los límites del fichero.
Designaremos con la variable "I" al identificativo del registro y con "DA" a la dirección de almacenamiento. La fórmula que nos da la dirección de almacenamiento será la siguiente:
I = DA
Desafortunadamente, este método no es demasiado utilizado ya que tiene una serie de limitaciones tales como:
- El contenido del identificativo coincide exactamente con la dirección de almacenamiento.
- La numeración de lo identificativos debe ser continua, o con muy pocas lagunas.
- El fichero debe ser totalmente estable.
Direccionamiento por restas sucesivas
El direccionamiento por restas sucesivas se emplea en caso de que los identificativos de los registros estén por bloques, es decir, cuando en la configuración inicial hay bloques de identificativos que no existen. Esto puede ser, por ejemplo, en un fichero cualquiera que existan identificativos del 1 al 100, del 500 al 700 y del 800 al 1000. Se observa que desde el 101 al 499, del 701 al 799 hay dos bloques de identificativos que no pueden estar en el fichero. Cuando nos referimos a su configuración inicial, estamos indicando que los valores que a priori tomarán los identificativos no están ni estarán en ningún momento contemplados en el proceso.
Para calcular la dirección de almacenamiento, primero buscaremos los huecos, partiendo siempre del identificativo menor, es decir, desde el identificativo 1, hasta el primero dado. A continuación se analizarán los huecos entre los distintos bloques de los identificativos.
Supongamos que tenemos que manejar un fichero, en el que los identificativos de los registros están entre los siguientes márgenes:
/0100-0300/ /0350-0500/ /0900-1200/
Automáticamente se ve que los bloques entre los que están comprendidos los identificativos están distantes unos de otros, dejando entre sí varios huecos. Si utilizásemos el direccionamiento directo necesitaríamos reservar un mínimo de 1200 posiciones físicas en el fichero para poder almacenar todos los registros. Lo que está claro es que estos huecos se tienen que poder eliminar y para ello utilizaremos un algoritmo de transformación que los elimine.
Se ve claramente que los huecos en el fichero están desde el identificativo 0001 hasta el 0099, desde el 0301 hasta el 0349 y desde el 0501 hasta el 0899. Sabemos de antemano que estas opciones nunca serán ocupadas por ningún registro, ya que los identificativos no están en esos límites, y es por eso por lo que no necesitaremos reservar 1200 posiciones en el fichero, sino bastantes menos, ya que el número real de registros del fichero es bastante inferior.
Concretamente, en nuestro ejemplo el número de huecos por cada uno de ellos sería el siguiente:
0001-0099 = 99 huecos en el primer bloque.
0301-0349 = 49 huecos en el segundo bloque.
0501-0899 = 399 huecos en el tercer bloque.
Imaginemos que queremos almacenar un registro con identificativo
I = 136. Sabiendo que las primeras 99 posiciones están vacías, lo que hay que hacer es aprovecharlas. Para ello, restamos el valor del identificativo del valor total del primer hueco, es decir, de 99. La dirección de almacenamiento sería la siguiente:
DA = 136 - 99 = 37.
Para todos los efectos, el registro sigue teniendo identificativo 136, aunque realmente esté almacenado en una posición distinta a la que indica su identificativo.
Supongamos ahora que queremos almacenar un registro con identificativo I = 450. Aquí se ve que ya, además de estar desaprovechado el espacio del primer hueco, también está desaprovechado el espacio del segundo. La dirección de almacenamiento sería la correspondiente al valor de la clave, después de restar las posiciones desaprovechadas del primer y segundo hueco. La dirección de almacenamiento sería la siguiente:
DA = 450 - 49 - 99 =302.
Supongamos, por último, que el identificativo del registro estuviese ubicado en el tercer bloque. Para calcular su dirección de almacenamiento, habría que restar las cantidades correspondientes a todos los huecos del fichero. Si, por ejemplo, quisiéramos almacenar el registro con identificativo 1200, la dirección de almacenamiento sería:
DA = 1200 - 399 - 49 - 99 = 653.
En este último ejemplo, además, queda de manifiesto cuál será el número total de posiciones necesarias que tenemos que utilizar para almacenar todos los registros del fichero. Se ve que con un total de 653 posiciones físicas podemos almacenar un número igual de registros, pero con claves superiores en casi el doble en valor numérico.
Este tipo de transformación matemática no produce sinónimos. Es obvio que la posición de almacenamiento siempre será real, sea cual fuere el valor del identificativo.
Direccionamiento por división
Consiste en dividir el valor del identificativo por el número de direcciones físicas asignadas al fichero + 1. El resto de la división indicará la dirección de almacenamiento. Este método, además, produce colisiones ya que el resto de la división seguramente sea el mismo para dos o más registros con distinto identificativo.
Direccionamiento por el centro del cuadrado
El método de direccionamiento por el centro del cuadrado consiste en averiguar la dirección de almacenamiento después de realizar las siguientes tareas:
- Elevar el identificativo al cuadrado. (A)
- Del resultado, eliminar la cifra de los extremos. (B)
- Hacer que el número quede comprendido entre 0 y 1. (C)
- Multiplicar el número obtenido por el número máximo de direcciones disponibles en el fichero. (D)
- Despreciar la parte decimal.
El resultado de todos estos cálculos indicará la dirección física de almacenamiento. Lógicamente, este método produce sinónimos. La cantidad de sinónimos producidos irá en relación directa con el número de cifras que se desprecien. Cuantas más cifras se desprecien mayor será el número de colisiones producidas y, además, el número total máximo de direcciones físicas del fichero será menor.
Supongamos que queremos almacenar el registro con identificativo
I = 3240 y con un total de 1200 posiciones físicas reservadas para el fichero. La dirección de almacenamiento se calculará de la forma siguiente:
A = 3240 * 3240 = 10497600
B = 10497600 = 10|4976|00
C = 4976 normalizado = 0,4976
D = 0,4976 * 1200 = 597,12
DA = 597
Direccionamiento por plegamiento
El direccionamiento por plegamiento se usa generalmente cuando los identificativos de los registros son muy grandes. El cálculo de la dirección de almacenamiento se realiza, en primer lugar, dividiendo en dos partes el identificativo, (plegándolo). A continuación se suman las dos partes, suprimiéndose un número determinado de cifras a la izquierda de la cantidad.
En este tipo de almacenamiento también se producen sinónimos ya que el resultado para dos identificativos distintos puede ser el mismo. El número de sinónimos está en relación directa al número de cifras que se desprecien. Cuantas más cifras se desprecien, mayor número de colisiones se producirán; y cuantas menos cifras, menos colisiones, aunque despreciar pocas cifras implica posiciones de almacenamiento que serán con seguridad demasiado grandes.
Supongamos que queremos almacenar el registro con identificativo
I = 376843. La dirección de almacenamiento se calcula de la siguiente forma:
I = 376843 I1 = 376 I2 = 843
DA = I1 + I2 = 376 + 843 = 1319
DA = 1|319 = 319
Direccionamiento por truncamiento
El direccionamiento por truncamiento permite reducir la longitud de un identificativo. Cuando se aplica el truncamiento en el identificativo inicial es porque se conoce perfectamente la distribución de los registros en el fichero y los identificativos se pueden reducir.
Realmente, el truncamiento consiste en eliminar alguna cifra, bien de la derecha, bien de la izquierda del identificativo. El resultado indicará la dirección de almacenamiento.
Supongamos un identificativo I = 19786: truncando las dos cifras de la izquierda resulta 19|786. La dirección de almacenamiento será DA =786.
Evidentemente, este tipo de direccionamiento también genera colisiones, aunque el número de éstas dependerá directamente del número de cifras truncadas.
Direccionamiento por cambio de base de numeración
Este procedimiento consiste en transformar un número decimal a otra base de numeración. Generalmente la base que se utiliza es de número primo, por ejemplo la 11.
Supongamos el identificativo I = 1978. Transformando el identificativo a base 11, su resultado será la dirección de almacenamiento.
DA = 1539
Direccionamiento por multiplicación
Normalmente, se puede multiplicar el identificativo por un número constante (preferiblemente primo), multiplicar entre sí dos partes de identificativo o multiplicar el identificativo por sí mismo. El resultado de cualquiera de estas operaciones indicará la posición física de almacenamiento.
Este tipo de direccionamiento tiene un gran inconveniente y es que a veces los límites físicos de fichero son superados. Es entonces cuando hay que aplicar cualquier otro método para reducir el valor de la dirección.
CONVERSIÓN DE IDENTIFICATIVOS ALFABÉTICOS.
DIRECCIONAMIENTO POR CONVERSIÓN BINARIO-OCTAL.
El mecanismo consiste que en a cada letra del alfabeto se le asigna un número que corresponde a la posición que cada una de ellas ocupe en el mismo. A cada letra se le asigna su valor ordinal.
A=1, B=2, C=3 ..........
La dirección de almacenamiento se deduce después de sumar los valores ordinales de las letras que forman el identificativo. Una vez obtenido el resultado numérico, este se pasa a binario. La forma de pasarlo a binario es dividiendo sucesivamente el número por dos hasta que el cociente sea igual o menor que uno. Sabiendo que cada tres dígitos binarios forman un dígito octal, los bits obtenidos como resultado se agruparán de tres en tres, de derecha a izquierda.
Inevitablemente se producirán colisiones, ya que el resultado obtenido después de sumar la letras que componen el identificativo puede ser el mismo. Además, ocurre que al utilizar el alfabeto octal como resultado final de la conversión, y al utilizar éste solamente los dígitos del 0 al 7, los dígitos 8 y 9 son utilizados, reduciendo así el número total de posiciones posibles físicas de almacenamiento. Es de suponer que los huecos estarán siempre en las últimas pistas, concretamente la 8 y la 9.
La única solución es utilizar una pista cuya dirección sea 8 y 9 como pistas de desbordamiento, paliando en gran medida el problema que esto plantea.
Supongamos que queremos calcular la dirección de almacenamiento del registro cuyo identificativo alfabético es I = GARCIA.
G A R C I A
7 1 18 3 9 1
Si sumamos todos los valores resulta el número 39.
39 codificado en binario es el número: 100111.
Desglosado, queda 100 y 111.
Pasando a octal, resulta 4 y 7.
La dirección de almacenamiento es DA=47.
Supongamos a continuación, por ejemplo, el identificativo I=LOPEZ. La suma de sus letras es 73. Si quisiéramos almacenar un registro con identificativo I=MATEOS cuya suma también es 73, estaríamos en un claro ejemplo de colisión.
CONVERSIÓN DE IDENTIFICATIVOS ALFANUMÉRICOS.
DIRECCIONAMIENTO POR ASOCIACIÓN
Es posible que sean los registros con identificativos alfanuméricos los que provoquen más problemas a la hora de transformarlos en direcciones física de almacenamiento.
El cálculo más práctico y más efectivo que hay es asociar a cada identificativo una dirección lógica asociada a una tabla. Entre el valor del identificativo y el contenido de la tabla no hay ninguna relación lógica. Es el usuario el que decide el contenido de la tabla.
En el momento de la creación del fichero se obtiene la dirección de almacenamiento de cada registro y se confecciona una lista de referencias cruzadas entre las claves y sus direcciones físicas.
Generalmente, esta lista está impresa y es la persona que utiliza el ordenador la que tiene que asignar a cada identificativo si dirección.
Es un direccionamiento rápido, ya que el único inconveniente que presenta es tener que consultar previamente la tabla (lista). Una vez consultada, el acceso al registro es directo.
Este tipo de direccionamiento se utilizará en ficheros muy estables y con un número máximo de registros no demasiado grande.
Ocurre que si esta tabla es lo suficientemente grande como para contener la posición asociada a cada registro, sucederá que este método de conversión no producirá sinónimos, ya que es fácilmente deducible que cada elemento de la tabla contendrá una dirección distinta.
La forma real de calcular la dirección es asociar a cada identificativo un subíndice que indique una posición de la tabla en la que estará la contenida la dirección real de almacenamiento del registro.
9.6. MÉTODO HASH (O DISPERSIÓN)
Este método proporciona una posibilidad de búsqueda de alta velocidad. Se utiliza cuando el valor de la clave es muy grande respecto al número total máximo de registros que se pueden almacenar en el fichero.
Es un método de acceso a ficheros para aquellos que sufren frecuentes actualizaciones, y está diseñado para localizar un registro como máximo con dos accesos a fichero.
Consiste en comprimir los identificativos de un tamaño relativamente grande a un tamaño más pequeño en relación con una dirección. Esto se obtiene realizando alguna operación con el identificativo obteniendo así la entrada al fichero, es decir, en qué posición se encuentra el registro con ese identificativo.
La rapidez que presenta este método está en contraposición al almacenamiento, ya que el número total de registros que se almacenen utilizando este método no puede ser muy elevado.
En este tipo de direccionamiento también se producen colisiones, es decir, ya que los diferentes caminos que podemos seguir para obtener la posición de almacenamiento producen resultados iguales. Los tipos de transformaciones son los siguientes:
a) División
La clave se divide por un número entero, algo menor al total de direcciones del fichero, indicando el resto de esta división la dirección de almacenamiento. Es conveniente que el número utilizado como divisor sea primo.
Ejemplo:
Supongamos un fichero con 9999 posiciones tope y la clave 12345
12345 dividido por 9997 resulta:
cociente = 1 y resto = 2348
DA = 2348
b) Plegamiento:
El identificativo se divide en varias partes tomando un número total de dígitos inferior al número total de registros del fichero. Estos bloques se suman o se enfrentan con alguna operación lógica como or, and, xor... etc.
Ejemplo:
Supongamos un fichero con 9999 posiciones tope y la clave 12345678.
1234|5678 que sumadas = 6912 DA = 6912
(dirección de almacenamiento).
c) Pseudo-azar:
El identificativo se utiliza como entrada de un generador de números casual (RANDOMIZE) indicando la salida de éste la dirección de almacenamiento.
Como se puede ver claramente, tanto si dividimos o plegamos el pseudo-azar, corremos el riesgo de tener colisiones. En este direccionamiento es prácticamente imposible eliminar este problema.
En general se emplean identificativos de tipo numérico ya que utilizar identificativos de tipo alfabéticos implicaría tener corresponder a cada letra del alfabeto su valor numérico en el código de la máquina. ASCII, EBCDIC... etc.
De estas técnicas mencionadas dentro del direccionamiento HASHING, se recomienda utilizar la de la división, ya que además de ser la más sencilla es la más efectiva.
Esta técnica recibe el nombre de difusión de almacenamiento tiene una gran ventaja frente a las dos restantes y es la de manejar los sinónimos (colisiones) con gran facilidad.
De todas formas, en el direccionamiento HASHING el problema de los sinónimos es bastante serio. Cuando se produce un sinónimo, éste va a parar a la zona reservada para tal fin. Automáticamente se localiza cuál es la primera posición vacía en esta zona y ahí se almacena el registro. Por ejemplo, si la primera posición está ocupada, se investiga la siguiente; si aún sigue ocupada, la siguiente y así hasta encontrar un hueco. Ocurre entonces que en un determinado momento los sinónimos serán tantos que el tiempo de acceso a esta zona será demasiado grande. Este modo de gestionar los sinónimos mediante HASHING recibe el nombre de agrupación primaria.
Cuando se utiliza la técnica de pseudo-azar y cuando se produce una colisión, puede ocurrir que la dirección de salida del generador aleatorio no corresponda con la de la tabla, consultándose entonces una posición posterior. Se calcula entonces el desplazamiento llamado OFFSET, el cual, sumando la posición original, indicará la posición de almacenamiento real del registro. Esta forma de gestionar los sinónimos recibe el nombre de agrupación secundaria.
Teniendo en cuenta que el manejo de sinónimos es complicado en cualquier técnica de direccionamiento, el HASHING con los métodos de agrupación primaria y agrupación secundaria subsana en parte el problema planteado por las colisiones.
El HASHING es un algoritmo rápido utilizado cuando el valor de la clave es demasiado grande. Gestiona los sinónimos de forma bastante efectiva.
9.8.2 FICHEROS RELATIVOS EN “C”
El sistema de ficheros de C proporciona dos funciones pertenecientes al ANSI que nos permiten un acceso directo a los datos almacenados en un fichero, proporcionándonos una ventaja frente a otros lenguajes de programación, que es el desplazamiento byte a byte a lo largo de un fichero. Estas dos funciones son: fseek() y ftell().
FSEEK()
Se encuentra en la librería “stdio.h”. Devuelve 0 si se ejecuta correctamente y un valor distinto de cero si se produce algún error.
Permite acceder directamente a una posición dentro del fichero partiendo de una posición origen.
No es recomendable el uso de esta función con ficheros de texto, ya que puede provocar un mal funcionamiento o resultados no esperados debido a las conversiones de caracteres lo que puede originar errores de localización. El uso de esta función está recomendado sólo para ficheros binarios.
El formato es el siguiente:
int fseek(FILE *Nombre_fichero, long Num_bytes, int origen);
Donde Nombre_fichero es el nombre de la corriente o flujo de datos sobre el que queremos realizar un acceso directo. Num_bytes es un valor numérico entero que indica el número de bytes que nos queremos desplazar a partir del origen, permitiéndonos acceder a una nueva posición directamente. Y, por último, Origen es una macro definida en el fichero cabecera “stdio.h”, que me marca el lugar o punto dentro del fichero, desde el que se efectúa el desplazamiento. Esta macro toma tres posibles valores que son:
Nombre del fichero | Origen | Valor en “stdio.h” |
SEEK_SET SEEK_CUR SEEK_END | Principio del fichero Posición actual Final del fichero | 0 1 2 |
FTELL()
Esta función está íntimamente relacionada con la función fseek().
Se encuentra en la librería “stdio.h”, y recibe un único parámetro que es un puntero de tipo FILE que indica el nombre lógico del fichero.
Devuelve el valor actual del indicador de posición de flujo o fichero especificado. Este valor se corresponde con el número de bytes desde el principio del fichero hasta el indicador de posición. En caso de producirse algún error la función devuelve -1L. Al devolvernos el valor actual del indicador de posición, nos permite en todo momento conocer nuestra situación exacta dentro del fichero.
El formato es el siguiente:
int ftell(FILE *Nombre_fichero);
EJEMPLOS
#include <stdio.h>
#include <string.h>
main()
{
char cadena [80];
char Nombre[][19]={
“Algebra = 6.25”,
“Estadística = 7.75”,
“Física = 3.25”
};
int k;
FILE *fich;
if ((fich = fopen (“Notas.alu”, “wb+”)) != NULL)
{
for (k=0; k<3; k++)
fprintf(fich, “%s”, Nombre[k]);
}
fseek(fich, strlen(Nombre[0]), SEEK_SET);
fgets(cadena, strlen(Nombre[1]), fich);
printf(“Nota de %s\n”, cadena);
fseek(fich, strlen(Nombre[2]), SEEK_END);
fgets(cadena, strlen(Nombre[1]), fich);
printf(“Nota de %s\n”, cadena);
fclose(fich);
}
1.- Creación de una guía telefónica.
Este programa es una guía telefónica que utiliza los ficheros de forma secuencial y directa. Lo crea secuencialmente, pero a la hora de modificar algún dato se utiliza el acceso directo para ir a ese registro en concreto. Para esto utilizamos la función fseek().
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
struct pp
{
char nombre[30];
char tel[10];
};
int numbytes=sizeof(struct pp);
FILE *puntf;
typedef struct pp estruct;
estruct ficha;
void añadir(void);
void cambiar(void);
void borrar(void);
void listar(void);
void crear(void);
void menu(void);
void main(void)
{
char car;
clrscr();
while(1)
{
menu();
car=getchar(); fflush(stdin);
car=tolower(car);
switch(car)
{
case `c': crear();break;
case 'a': añadir();break;
case `l': listar();break;
case `m': cambiar();break;
case `b': borrar();break;
case `s': exit();break;
}
}
} /* final de main */
void crear(void)
{
puntf=fopen(“datos”, “wb”);
fclose(puntf);
}
void añadir(void)
{
puntf=fopen(“datos”, “ab”);
printf(“\n Para parar la ejecución pulsar CTRL+Z \n\n NOMBRE: “);
while(gets(ficha.nombre)!=NULL)
{
printf(“ TELEFONO: “);
gets(ficha.tel); fflush(stdin);
fwrite(&ficha,numbytes,1,puntf);
printf(“\n NOMBRE: “);
}
fclose(puntf);
}
void listar(void)
{
int c=0,i=0;
clrscr();
printf(“ Listado de Guía Telefónica \n_____________________\n”);
puntf=fopen(“datos”, “rb”);
while(!feof(puntf))
{
fread(&ficha,numbytes,1,puntf);
if(!feof(puntf))
printf(“\n %s\t\t\t%s”,ficha.nombre, ficha.tel);
c++;
if(c==i*25)
{
printf(“-------------Pulsa [ENTER]-------------”);
i++;
getchar();
}
}
fclose(puntf);
printf(“\n pulsa [ENTER]”);
getchar();
}
void cambiar(void)
{
int n;
char car;
puntf=fopen(“datos”, “r+b”);
printf(“¿Qué número? ”);
scanf(“%d”, &n); fflush(stdin);
fseek(puntf,(n-1)*numbytes,0);
fread(&ficha,numbytes,1,puntf);
printf(“%s %s”, ficha.nombre,ficha.tel);
printf(“\n Cambiar (s/n): “);
car=getchar(); fflush(stdin);
if(car=='s')
{
printf(“Nombre: ”);
gets(ficha.nombre); fflush(stdin);
printf(“Teléfono: “);
gets(ficha.tel); fflush(stdin);
fseek(puntf,(n-1)*numbytes,0);
fwrite(&ficha,numbytes,1,puntf);
}
fclose(puntf);
}
void borrar(void)
{
int j,n,i=0;
estruct fic[10];
listar();
printf(“\n ¿Qué número? ”);
scanf(“\n %d”, &n); fflush(stdin);
puntf=fopen(“datos”, “rb”);
do
{
fread(&fic[i++], numbytes,1,puntf);
}
while(!feof(puntf));
i--;
fclose(puntf);
puntf=fopen(“datos”, “wb”);
for (j=0;j<i;j++)
{
if(j!=n-1)
fwrite(&fic[j],numbytes,1,puntf);
}
fclose(puntf);
}
void menu(void)
{
clrscr();
printf(“\n\n\n\tGUIA TELEFONICA\n\t_________________\n\n\n);
printf(“\n\t (C) Crear nuevo fichero”);
printf(“\n\t (A) Agregar nuevo registro”);
printf(“\n\t (L) Listar un fichero”);
printf(“\n\t (M) Modificar un registro”);
printf(“\n\t (B) Borrar un registro”);
printf(“\n\t (S) Salir del programa);
printf(“\n\n\n\t Elige una opción: “);
}
2. Este programa realiza un menú que actualiza un fichero relativo con direccionamiento indirecto.
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <iostream.h>
struct datos{
char apellidos [40] ;
char nombre [20] ;
int numper ;
long dni ;
char ocupado ;
} ;
void main (void)
{
void menu (void) ;
void alta (FILE * ) ;
void baja (FILE * ) ;
void modificacion (FILE * ) ;
void consulta (FILE * ) ;
void listado (FILE * ) ;
int opcion ;
FILE *f ;
if ( (f = fopen ( "a : /binario/huecos", "r + b") ) = = NULL)
{
puts ( " Fichero no existente " ) ;
exit (1) ;
}
clrscr ( ) ;
menu ( ) ;
printf ( "\n \nIntroduce la opcion : \n " ) ;
cin>>opcion ;
while ( opcion !=6 )
{
switch (opcion)
{
case 1 : alta ( f ) ;
break ;
case 2 : baja ( f ) ;
break ;
case 3 : modificacion ( f ) ;
break ;
case 4 : consulta ( f ) ;
break ;
case 5 : listado ( f ) ;
break ;
default : printf ( " Opción introducida errónea. \n" ) ;
break ;
}
clrscr ( ) ;
menu ( ) ;
printf ( "\n \nIntroduce la opción : \n" ) ;
cin>>opcion ;
}
fclose ( f ) ;
}
/* función que visualiza el menú en pantalla */
void menu (void)
{
printf ( " Las opciones del menú son : \n " ) ;
printf ( " \n \t1. Altas. \n " ) ;
printf ( " \t2. Bajas. \n " ) ;
printf ( " \t3. Modificación. \n " ) ;
printf ( " \t4. Consulta. \n " ) ;
printf ( " \t5. Listado. \n " ) ;
printf ( " \t6. Fin de proceso. \n " ) ;
}
/* función que da de altas en el fichero */
void existe ( FILE *, long, int * , int * ) ;
void grabar ( FILE *, long, int, int ) ;
void alta ( FILE *fp )
{
long iden ;
int sw, grabar_dire ;
printf ( " Introduce la clave del registro a dar de alta : \n " ) ;
cin>>iden ;
existe ( fp , iden, &grabar_dire, &sw ) ;
grabar ( fp, iden, grabar_dire, sw ) ;
}
/* función que comprueba si el registro ya existe */
void existe ( FILE *fp, long identi, int *dir, int *sw )
{
int aux ;
struct datos r ;
* sw = 0 ;
aux = identi%241 ;
*dir = 1000 ;
fseek ( fp, aux*sizeof ( struct datos ), SEEK_SET ) ;
fread ( &r, sizeof (struct datos ), 1, fp) ;
if ( ( r.ocupado = = `s` ) && ( r.numper = = identi ) )
*sw=1 ;
else
{
if ( r.ocupado = = `n` )
*dir=aux ;
aux=241 ;
while ( ( aux<300 ) && (*sw= = 0 ) )
{
fseek ( fp, aux*sizeof ( struct datos ), SEEK_SET ) ;
fread ( &r, sizeof ( struct datos ), 1, fp ) ;
if ( ( r.ocupado= = `s` ) && ( r.numper= =identi ) )
*sw=1 ;
else
if ( ( r.ocupado= = `n` ) && ( *dir= =1000) )
*dir=aux ;
aux++ ;
}
}
}
FUNCIÓN QUE GRABA EL REGISTRO
void grabar ( FILE *fp, long identi, int dir, int sw )
{
struct datos r ;
if ( sw= =1 )
printf ( " Imposible dar de alta. REGISTRO YA EXISTENTE. \n " ) ;
else
if ( dir= =1000)
printf ( "Imposible dar de alta. FICHERO
LLENO. \n ") ;
else
{
printf ( " Introduce el nombre : " ) ;
gets ( r.nombre ) ;
printf ( "\nIntroduce los apellidos : " ) ;
gets ( r.apellidos ) ;
printf ( "\nIntroduce el DNI : " ) ;
cin>>r.dni ;
fflush ( stdin ) ;
r.numper = identi ;
r.ocupado = `s` ;
fseek ( fp, dir*sizeof ( struct datos ), SEEK_SET ) ;
fwrite ( &r, sizeof ( struct datos ), 1, fp ) ;
}
}
FUNCIÓN QUE DA DE BAJAS EN EL FICHERO
void baja ( FILE *fp )
{
int aux, identi, sw=0 ;
struct datos r ;
printf ( " Introduce el número de personal a dar de baja : " ) ;
cin>>identi ;
aux=identi%241 ;
fseek ( fp, aux*sizeof (struct datos ), SEEK_SET ) ;
fread ( &r, sizeof ( struct datos ), 1, fp ) ;
if ( ( r.ocupado= = `s`) && ( r.numper= =identi ) )
{
r.ocupado= `n` ;
fseek ( fp, aux*sizeof (struct datos), SEEK_SET ) ;
fwrite ( &r, sizeof ( struct datos ), 1, fp ) ;
sw=1 ;
}
else
{
aux=241 ;
while ( ( aux<300 ) && ( sw= =0 ) )
{
fseek ( fp, aux*sizeof (struct datos), SEEK_SET ) ;
fread ( &r, sizeof (struct datos), 1, fp) ;
if ( ( r.ocupado= =`s` ) && ( r.numper= =identi ) )
{
r.ocupado=`n` ;
fseek ( fp, aux*sizeof ( struct datos), SEEK_SET ) ;
fwrite ( fp, sizeof ( struct datos ), 1, fp) ;
sw=1 ;
}
aux++ ;
}
if ( sw= =0 )
printf ( " REGISTRO NO EXISTE.\n " ) ;
}
printf ( "\nEL REGISTRO HA SIDO BORRADO" ) ;
printf ( "\n \nPulse una tecla para continuar. " ) ;
getchar ( ) ;
}
FUNCIÓN QUE MODIFICA REGISTROS DEL FICHERO
struct datos modificar ( struct datos ) ;
void existe ( FILE *, long, int *, int * ) ;
void modificacion ( FILE *fp )
{
int aux, identi, sw= 0 ;
struct datos r ;
printf ( "Introduce el número de personal a modificar : ") ;
cin>>identi ;
aux=identi%241 ;
fseek ( fp, aux*sizeof ( struct datos ), SEEK_SET ) ;
fread ( &r, sizeof ( struct datos ), 1, fp ) ;
if ( ( r.ocupado= =`s`) && ( r.numper= =identi ) )
{
r = modificar ( r ) ;
sw = 1 ;
}
else
{
aux = 241 ;
while ( ( aux<300) && ( sw= =0 ) )
{
fseek ( fp, aux*sizeof ( struct datos), SEEK_SET ) ;
fread (&r, sizeof ( struct datos ), 1, fp ) ;
if ( ( r.ocupado= =`s`) && ( r.numper= =identi ) )
{
r = modificar ( r ) ;
sw = 1 ;
}
aux ++ ;
}
}
if ( sw= =0 )
printf ( " REGISTRO NO EXISTENTE. \n" ) ;
fseek ( fp, aux*sizeof (struct datos ), SEEK_SET ) ;
fwrite ( &r, sizeof ( struct datos ), 1, fp ) ;
printf ( " \n \nPulsa una tecla para continuar. " ) ;
getchar ( ) ;
}
FUNCIÓN QUE MODIFICA LOS DATOS DE UN REGISTRO
struct datos modificar (struct datos reg )
{
char opc ;
printf ( " ¿Quieres cambiar el nombre ( s/n ) ? \n " ) ;
cin>>opc ;
if ( opc= = `s`)
{
printf ( "Introduce el nombre : ") ;
gets ( reg.nombre ) ;
}
printf ( "¿Quieres cambiar los apellidos (s/n) ? \n ") ;
cin>>opc ;
if ( opc= = `s`)
{
printf ( \nIntroduce los apellidos : ") ;
gets ( reg.apellidos ) ;
}
printf ( " ¿Quieres cambiar el DNI (s/n) ? \n" ) ;
cin>>opc ;
if ( opc= =`s` )
{
printf ( "\nIntroduce el DNI : " ) ;
cin>>reg.dni ;
}
fflush ( stdin ) ;
return ( reg ) ;
}
FUNCIÓN QUE CONSULTA REGISTROS
void visualizar (struct datos) ;
void consulta ( FILE *fp )
{
int identi, aux, sw=0 ;
struct datos r ;
printf ( "Introduzca el número de personal : " ) ;
cin>>identi ;
aux=identi%241 ;
fseek ( fp, aux*sizeof (struct datos ), SEEK_SET ) ;
fread ( &r, sizeof (struct datos ), 1, fp ) ;
if ( ( r.ocupado= =`s`) && ( r.rumper= =identi ) )
{
visualizar ( r ) ;
sw = 1 ;
}
else
{
aux=241 ;
while ( ( aux<300 ) && ( sw= =0) )
{
fseek ( fp, aux*sizeof (struct datos ), SEEK_SET ) ;
fread ( &r, sizeof ( struct datos ), 1, fp ) ;
if ( ( r.ocupado= =`s`) && (r.numper= =identi ) )
{
visualizar ( r ) ;
sw = 1 ;
}
aux ++ ;
}
}
if ( sw= =0 )
printf ( "REGISTRO NO EXISTENTE. \n" ) ;
printf ( "\n \nPulsa una tecla para volver al menú. " ) ;
getchar ( ) ;
}
FUNCIÓN QUE VISUALIZA LOS DATOS DE UN REGISTRO
void visualizar (struct datos reg )
{
printf ( "\n El nº de personal es : %d", reg.numper ) ;
printf ( "\n El nombre del empleado es: %s", reg.nombre ) ;
printf ( "\n Los apellidos del empleado son: %s", reg.apellidos ) ;
printf ( "\n El DNI del empleado es: %ld \n\n", reg.dni ) ;
}
FUNCIÓN QUE REALIZA UN LISTADO COMPLETO DEL FICHERO
void visualizar (struct datos ) ;
void listado ( FILE *fp )
{
clrscr ( ) ;
struct datos r ;
int con=0 ;
rewind ( fp ) ;
while ( feof ( fp ) = = 0 )
{
if ( r.ocupado = = `s`)
{
cont=cont+5 ;
visualizar ( r ) ;
if ( cont>15)
{
printf ( "\n\nPulsa una tecla para continuar. \n" ) ;
getchar ( ) ;
cont = 0 ;
clrscr ( ) ;
}
}
fread ( &r, sizeof (struct datos ), 1, fp ) ;
}
printf ( "\n\nPresiona una tecla para salir. \n ) ;
getchar ( ) ;
}
TEMA 10
10. FICHEROS SECUENCIALES
INDEXADOS
10.1 Introducción
10.2 Organización
10.3 Tablas de gestión
10.4 Tipos de acceso
10.5 Operaciones
10.6 Tratamientos
10.7 Ejemplos
INTRODUCCION
La organización secuencial es de gran utilidad en ficheros con un elevado número de registros, que no requieren actualizarse con excesiva frecuencia.
Esta organización presenta dos problemas:
- Siempre que se actualice el fichero, se debe crear uno nuevo, ya que no es posible efectuar altas intermedias o bajas de registros sobre el propio fichero.
- Para acceder a un registro concreto, es necesario haber leído previamente todos los registros que le preceden. Es decir, el único modo de acceso que admite un fichero secuencial es el secuencial.
Estos inconvenientes se pueden solucionar en gran medida con otro tipo de organización, la organización secuencial indexada, que va a hacer posible el acceso casi directo a un determinado registro, así como la realización de altas y bajas sobre el mismo.
10.2 ORGANIZACION
Este tipo de organización aprovecha lo mejor de la organización secuencial (tratamiento de grandes volúmenes de información) y lo mejor de la organización directa (acceso rápido y directo a los registros).
En este tipo de ficheros vamos a tener dos partes fundamentales: una donde se almacenan los datos y la otra donde se encuentran las diferentes tablas de índices. Si vamos a utilizar una tabla de índices secuenciada y ordenada, los registros han de estar ordenados por su idenftificativo. El acceso a los registros se hará consultando previamente la tabla de índices.
Este tipo de ficheros requiere estar almacenado en un soporte de acceso directo (disco duro, disquete, ect.).
La organización secuencial indexada exige que todos los registros que forman el fichero contengan un campo denominado campo clave. Este campo servirá para identificar cada registro de forma única, no pudiendo existir en un mismo fichero dos registros con el mismo contenido en dicho campo clave. Por este campo se graban, en orden ascendente, los registros del fichero indexado, para que se pueda localizar un determinado registro en él.
Así por ejemplo, si en un centro educativo se pretendiese utilizar un fichero que almacenase los datos de sus alumnos, el campo clave de los registros de este fichero podría ser el número de matrícula, ya que todos los alumnos tienen uno asignado y no pueden existir dos alumnos con el mismo número. Sin embargo, nunca podría utilizarse como campo clave el nombre del alumno, ya que seguramente habría numerosos registros con el mismo nombre.
La gestión interna de los ficheros secuenciales indexados depende del sistema en el que se desarrollen. Un fichero secuencial indexado consta de tres áreas, que suelen ser, a su vez, ficheros.
Area primaria
También denominada como área de datos, ya que en ella se almacenan físicamente los datos de los registros. Los registros se graban cuando se crea el fichero, en orden ascendente del campo clave. Esta área tiene organización secuencial y se puede decir que está dividida dentro del soporte en varios grupos, todos ellos de igual tamaño (pistas, cilindros, etc.).
Area de índices:
El área de índices es también un fichero con organización secuencial. Cada registro del mismo lo forman dos campos. El primero contiene la clave más alta de los registros que componen el grupo, es decir, la clave de su último registro. El segundo campo contiene la dirección absoluta del primer registro de ese grupo.
Area de excedentes:
También denominada como área de overflow. En esta área se van a grabar los registros dados de alta en las actualizaciones. Por tanto, cuando se crea el fichero, no se introduce ningún registro en ella, es decir, se crea vacía.
Por consiguiente, en el momento de la creación de un fichero secuencial indexado, se debe introducir los registros en orden ascendente del campo clave. El sistema los grabará en el área primaria e irá generando el área de índices.
Un esquema de las tres áreas de un fichero indexado que se acaba de crear podría ser el siguiente:
Area primaria
Pista 01
A1 | REG1 | A7 | REG2 | B3 | REG3 | B8 | REG4 |
Campos clave
Pista 02
C5 | REG5 | C9 | REG6 | D2 | REG7 | D5 | REG8 |
Campos clave
Pista 03
E3 | REG9 | E8 | REG10 | F5 | REG11 | F8 | REG12 |
Area de Indices
B8 | 01 | D5 | 02 | F8 | 03 |
Area de excedentes
Campo clave
ORGANIZACIÓN SECUENCIAL ENCADENADA
Esta organización se da en aquellos ficheros con organización secuencial a los que se les añade un campo adicional de tipo puntero y que nos indica cual es el siguiente o anterior registro en secuencia lógica.
En este tipo de ficheros las inserciones se realizan siempre por el final y se almacenan según van llegando. La secuencia física y la lógica de los registros no coinciden, puede ser que el ultimo registro que se inserte sea el primero en la secuencia lógica del fichero.
Las bajas se realizan marcando los registros para que en futuros procesos sean ignorados. Las bajas van deteriorando progresivamente el fichero ya que no son ocupadas por futuras inserciones de registros.
Los ficheros con esta organización tienen al principio del mismo un registro adicional especial, llamado cabecera, con el fin de guardar la dirección del primer registro en la secuencia lógica del fichero. Esta dirección del primer registro lógico se guarda en un campo tipo puntero del registro de cabecera.
Después de abrir el fichero se lee en primer lugar el registro de cabecera, que será el que se encuentra físicamente en la primera posición de ese fichero en el soporte de almacenamiento.
Los punteros se caracterizan fundamentalmente por:
- Ser de longitud fija.
- Estar situados dentro del registro.
- Generalmente los punteros se sitúan al final de cada registro. El usuario puede utilizar los punteros que considere necesarios. Por cada campo puntero que se guarde en el registro se puede obtener una secuencia lógica distinta con los registros del mismo fichero.
ORGANIZACIÓN SECUENCIAL INDEXADA-ENCADENADA
Este tipo de organización aprovecha lo mejor de las dos variantes de organización secuencial encadenada e indexada.
Se caracteriza por la utilización de punteros e índices de forma simultánea, lo que implica un considerable aumento del espacio ocupado en memoria para la implementación de índices y campos puntero, pero proporciona una gran rapidez en la búsqueda de registros.
En la eliminación de registros se generan huecos que realmente son posiciones de memoria ocupadas por registros marcados, pero que no han sido eliminados físicamente del fichero. La única posibilidad de eliminar dichos huecos es en futuras operaciones en las que se necesitará reorganizar el fichero.
En el caso de inserciones de nuevos registros, éstas se hacen directamente sobre la zona de desbordamiento, pues al ser variantes de la organización secuencial mantienen las mismas características y cualidades, no permitiendo la inserción de nuevos registros en el área primaria después de la creación del fichero.
Estos ficheros deben ser reorganizados periódicamente por dos motivos:
1.La eliminación de registros aumenta considerablemente el tamaño de los ficheros, ya que no se eliminan físicamente del dispositivo de
almacenamiento impidiendo así liberar el espacio de memoria
ocupado.
2.Las inserciones generan un área de excedentes excesivamente grande.
10.3- TIPOS DE ACCESO
Un fichero con organización secuencial indexada permite dos tipos de acceso diferentes: acceso secuencial y acceso directo. Algunos lenguajes admiten también otro tipo de acceso llamado acceso dinámico.
ACCESO SECUENCIAL
Debido a que un fichero secuencial indexado es secuencial, esta forma de acceso es similar a la de los ficheros secuenciales, es decir, se accede a los registros uno por uno desde el primero hasta el último.
Este tipo de ficheros tiene que tener un final. Este final debe ser detectado por el ordenador por una marca situada al final del fichero.
ACCESO DIRECTO
Consiste en acceder a un determinado registro indicando simplemente la clave del mismo. El fichero tendrá que estar almacenado en un soporte direccionable donde cada registro se corresponde a una dirección. También deberá estar ordenado por un identificativo.
Este método de acceso recibe el nombre de búsqueda dicotómica y consiste en el acceso directo a la dirección central del fichero, realizando una operación de lectura en dicha dirección y comparando el identificativo con el que estamos buscando, si coincide, entonces el proceso finaliza, en otro caso repetimos el proceso con la mitad candidata a contener el registro.
ACCESO DINÁMICO
Es una mezcla de los anteriores. Se accede directamente a un registro concreto y a partir de él, se accede secuencialmente a un grupo de registros que le siguen.
10.4- TABLAS DE GESTION
La organización secuencial indexada es eficaz tanto en consultas esporádicas como en consultas completas del fichero. En caso de realizar una consulta completa del fichero, no habrá ninguna dificultad, ya que su organización es secuencial. En cambio si necesitamos consultar algún registro, lo primero que debemos hacer es consultar la tabla de índices para averiguar en que dirección se encuentra el registro buscado.
Normalmente los índices están contenidos en tablas y se dividen en dos grandes niveles:
1- Indice de cilindro (directorio maestro): Cilindro es una zona del dispositivo físico de almacenamiento (normalmente un conjunto de discos (DISKPACK)), a la que las distintas cabezas de lectura tienen acceso al mismo tiempo. Cada cilindro tendrá tantas pistas como caras de discos tengamos en el diskpack.
2- Indice de pistas (subdirectorio): Normalmente cada cilindro contiene:
- Un conjunto de pistas en los que se almacenan los registros.
- Indice de pistas (subdirectorio) que tiene una entrada por
cada pista.
- Una o más pistas destinadas a zonas de desbordamiento.
La tabla de índice de cilindro se puede situar al principio o al final de la zona destinada al fichero.
Tabla de índices
MAX_CLAVE | DIRECCIONES |
5 | 1 |
9 | 4 |
19 | 7 |
FICHERO
INDICE | CLAVE_DATOS | |
1 | 1 | |
2 | 4 | |
3 | 5 | |
4 | 7 | |
5 | 10 | |
6 | 14 | |
7 | 18 | |
8 | 20 | |
9 | 27 | |
10 | 28 | |
11 | 29 | |
12 | 31 | |
La tabla del índice de pistas tiene dos partes, una normal y otra de desbordamiento. Cada una de estas partes se subdivide en otras dos:
1- Una zona normal que contiene:
-
identificativo del mayor registro de la pista.
-
Dirección del bloque que contiene el primer registro de la pista.
2- Una zona de desbordamiento que contiene:
-
indentificativo del mayor registro de la pista de desbordamiento.
-
Posición inicial del primer registro de la pista de desbordamiento.
La tabla de índice de pistas, al igual que la tabla de índice de cilindros se consultará de forma secuencial. Una vez encontrado su valor, la dirección indicará en la pista en que se supone que tiene que estar almacenado el registro. Esta pista será consultada secuencialmente hasta localizar el registro buscado.
En este tipo de organización se suele añadir al fichero una parte adicional llamada de desbordamiento que se utiliza para insertar nuevos registros una vez creado el fichero. Las zonas de desbordamiento se crearán o no dependiendo de las necesidades del programador. Las zonas de desbordamiento pueden existir directamente en cada cilindro o de forma independiente en un cilindro destinado a ese fin. En ficheros con pocas inserciones no se reservara zona de desbordamiento.
Los registros que se encuentran en la zona de desbordamiento se almacenan por orden de llegada por lo que no tienen porque estar ordenados.
Las eliminaciones de los registros son lógicas, es decir, se marcan, para que en posteriores procesos sean ignorados. La tabla no sufre ninguna modificación, ya que las posiciones de entrada a la tabla seguirán siendo las mismas. Si realizamos una consulta del fichero, los registros dados de baja son consultados aunque ignorados.
Si el fichero tuviera demasiadas bajas, quedaría bastante deteriorado teniendo que proceder a su reorganización. Esta reorganización consiste en eliminar físicamente los registros marcados en el proceso de baja, con el fin de eliminar espacios muertos dentro del fichero de datos. La mayoría de los lenguajes de programación poseen programas de utilidad para realizar la reorganización del fichero.
TABLA DE GESTIÓN PARA FICHEROS SECUENCIALES INDEXADOS
ALGORITMO INDEXACIÓN
INICIO
FICHERO1: fichero secuencial
RFICHERO1:
CLAVE_1: alfanumérico
CAMPOS: alfanuméricos
FICHERO2: fichero secuencial
RFICHERO2:
CLAVE_2: alfanumérico
CAMPOS: alfanumérico
TABLAS: ficheros secuencial
RTABLAS:
CLAVE_TABLA: alfanumérico
DIRECCION_TABLA: alfanumérico
SW, X: enteros
Abrir de entrada FICHERO1
Abrir de salida TABLAS, FICHERO2
Leer FICHERO1
Mientras no sea FF. FICHERO1 hacer
Para SW=1 hasta SW=5 hacer
Si SW=1 entonces
X dirección del primer registro
FinSi
Si SW=5 entonces
DIRECCION_TABLA X
CLAVE_TABLA CLAVE_1
Grabar RTABLAS
FinSi
Grabar RFICHERO2
Leer FICHERO1
FinPara
SW 1
FinMientras
Cerrar FICHERO1, FICHERO2, TABLAS
FIN
EXPLICACIÓN:
Este algoritmo sirve para transformar archivos secuencial a secuenciales indexados. El fichero original se introduce en otro y se escribe en el archivo TABLAS la ordenación (dirección y claves) del primer fichero. Agrupando los registros de cinco en cinco, con la dirección del comienzo de ese grupo de cinco y la clave del último de ellos.
TABLA DE GESTIÓN PARA SECUENCIALES INDEXADOS EN C
Algoritmo para pasar un fichero secuencial a un secuencial indexado (con tabla).
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
FILE *indexado, *secuencial, *secuindex;
struct indexado
{
int cod;
int direc;
};
struct secuencial
{
char nombre [50];
char apellido [50];
int cod;
};
struct secuindex
{
char nombre [50];
char apellido [50];
int cod;
char ocupado;
};
struct indexado index;
struct secuencial secu;
struct secuindex sein;
void main (void)
{
char *a;
int cont,direc;
clrscr();
puts (“Introduce el path nombre del fichero secuencial”);
gets(a);
puts (“se creará la tabla en el fichero \“indexa\”, y el nuevo fichero”);
gets(a);
/*Debemos crear el fichero indice primero con huecos */
if ((indexado=fopen(“a:\\indexa”, “wb”))==NULL)
{
puts(“Error de apertura (indexado)”);
exit(1);
}
index.cod=0;
index.direc=0;
for (cont=0; cont<300;cont++)
{
fwrite(&index, siceof(struct indexado),1,indexado);
}
fclose (indexado);
/* Abrimos los ficheros para crear el índice */
puts (“\n \t \t EL INDICE SE ESTA CREANDO”);
if((indexado=fopen(“a:\\indexa”, “r+b”))==NULL)
{
puts (“Error de apertura (indexado)”);
exit(1);
}
if ((secuencial=fopen(a,”rb”)))==NULL)
{
puts(“Error de apertura (directo)”);
exit(1);
}
if ((secuindex=fopen(“a:\\secuen”,”wb”))==NULL)
{
puts(“Error de apertura (directo)”);
exit(1);
}
/*en cada registro del índice apuntaremos al principio de un */ /*conjunto de cinco registros del secuencial */
fread(&secu, sizeof(struct secuencial),1,secuencial);
cont=1;
direc=0;
sein.ocupado=`s';
while(feof(secuencial)==0)
{
printf(“nombre -> %s\n”,secu.nombre);
printf(“apellido ->%s\n”, secu.apellido);
printf(“codigo -> %d\n”,secu.cod);
if (cont==5)
{
cont=1;
index.cod=secu.cod;
index.direc=direc;
direc+=5;
/*escribimos el código del último registro y la*/ /*dirección del primero*/
fwrite(&index,sizeof(struct indexado),1,indexado);
}
/* tenemos que pasar el registro del secuencial al nuevo /*fichero secuencial que tiene un campo más */
strcpy(sein.nombre,secu.nombre);
strcpy(sein.apellido,secu.apellido);
sein.cod=secu.cod;
fwrite(&sein,sizeof(struct secuindex),1,secuindex);
/*debemos volver a leer */
cont++;
fread(&secu,sizeof(struct secuencial),1,secuencial);
}
/*En el último registro de la tabla metemos la dirección de la */
/*zona de desbordamiento y un código imposible de superar */
index.cod=32000;
index.direc=direc;
fwrite(&index,sizeof(struct indexado),1,indexado);
/*Debemos crear en el nuevo secuencial una zona de */
/*desbordamiento*/
sein.cod=1111;
sein.ocupado=`n';
for(cont=0;cont<20;cont++)
fwrite(&sein,sizeof(struct secuindex),1,secuindex);
/*terminado el proceso de creación indexado*/
puts(“\n \t PROCESO TERMINADO”);
getch();
fclose(indexado);
fclose(secuenindex);
fclose(secuencial);
}
10.5- OPERACIONES CON FICHEROS SECUENCIALES
Según el acceso (secuencial o directo) se pueden realizar las siguientes operaciones con ficheros secuenciales:
Operaciones con acceso secuencial.
Operaciones con acceso directo.
OPERACIONES CON ACCESO SECUENCIAL
Las diferentes operaciones que se pueden realizar sobre los registros de un fichero con organización secuencial indexada, accediendo al mismo de modo secuencial, son las siguientes:
Lectura secuencial:
Un fichero con organización secuencial indexada tiene sus registros grabados físicamente en orden ascendente de clave dentro del área primaria. Por ello, se puede acceder a los mismos leyéndolos desde el primero hasta el último, de manera idéntica a como se accedería a un fichero secuencial ordenado por un determinado campo.
Aunque el fichero tenga registros grabados en el área de overflow, el sistema los gestiona de manera que, a efectos de programa, esta situación no influye en el proceso de lectura secuencial. Cuando se lee secuencialmente un fichero secuencial indexado, los registros se irán leyendo en orden creciente de claves, ya se encuentren en el área primaria o en el área de overflow.
El sistema detectará (igual que en los secuenciales) que el fichero ha finalizado cuando se lea la marca de fin de fichero.
Escritura o grabación secuencial:
La escritura secuencial consiste en grabar los registros teniendo en cuenta que éstos deben introducirse en el soporte en orden creciente de claves, siendo el propio sistema el que se encargará de gestionar el área de índices.
En general dicha operación se realizará con éxito salvo si se intentan grabar dos registros con la misma clave, o un registro con clave inferior a alguna de las anteriores, o bien si no cabe en el soporte otro registro, etc. En cualquiera de estos casos, el sistema detecta dicha situación y no graba el registro.
Después de una operación de escritura, se deberá preguntar por el éxito o fracaso de la misma.
Reescritura o regrabación secuencial:
En general, la reescritura de registros no existe en los ficheros con organización secuencial, aunque hay algunos lenguajes que la permiten, si el fichero secuencial está almacenado en un soporte de acceso directo.
Esta operación consiste en volver a grabar, en el soporte externo, un registro ya existente al que se le ha variado el contenido de alguno de sus campos, exceptuando su campo clave, ya que es el que lo identifica.
Se debe tener en cuenta que los ficheros sobre los que se vaya a realizar esta operación han de ser abiertos como de Entrada/Salida.
Ejemplo:
-
Una empresa guarda en un fichero secuencial indexado el prefijo y el número de teléfono de todos los clientes que viven en Madrid, siendo su descripción la siguiente:
CL_COD | CL_NOM | CL_PRE | CL_TEL |
El campo clave del fichero es CL_COD.
-
Si el Ministerio del Interior decidiese cambiar el prefijo telefónico de Madrid por el número 99, habría que recorrerse secuencialemtne el fichero y por cada registro leído, poner el nuevo prefijo al campo CL_PRE y escribir el registro modificado.
-
El pseudocódigo correspondiente a este proceso sería:
Inicio
Abrir de entrada/salida FCLIEN
Leer secuencialmente FCLIEN
Mientras no fin FCLIEN
CL_PRE=99
Reescribir sec. En FCLIEN
Leer sec. FCLIEN
Fin_mientras
Cerrar FCLIEN
Fin
Borrado secuencial:
Esta operación no existe en los ficheros con organización secuencial, consiste en borrar consecutivamente, es decir, uno después de otro, los registros del fichero.
Los registros no se borran físicamente del dispositivo, sino que el sistema los coloca una marca que los hace inaccesibles.
La operación de borrado secuencial de registros es poco usual, se utiliza más el borrado directo.
OPERACIONES CON ACCESO DIRECTO
Las diferentes operaciones que se pueden realizar sobre los registros de un fichero con organización secuencial indexada, accediendo al mismo de modo directo, son las siguientes:
Lectura directa:
Los ficheros con organización secuencial indexada poseen un área de índices, gracias al cual se puede acceder casi directamente a un registro, especificando su clave.
El sistema para localizar de forma directa un registro con una clave concreta, consulta el área de índices de forma secuencial hasta obtener el grupo donde debe hallarse dicho registro.
A continuación se posiciona al comienzo de ese grupo en el área de datos y lo recorre secuencialmente hasta localizar el registro buscado. Si no lo encuentra allí, se dirige al comienzo del área de overflow y la empieza a recorrer secuencialmente hasta hallarlo. Si tampoco lo encuentra, significa que el registro con esa clave no existe en el fichero.
En programación antes de indicar al sistema que realice una operación de lectura directa, hay que introducir en el campo clave el valor de la clave del registro al que se quiere acceder y, a continuación, dar la orden de lectura directa.
Por ejemplo, si se tiene un fichero de organización secuencial indexada, FCLIEN, que almacena los datos de los clientes de una empresa, con la siguiente descripción:
CL_COD | CL_NOM | CL_DIR | CL_TEL |
Siendo CL_COD el campo clave del fichero.
Si se deseara leer directamente el registro correspondiente al cliente de clave “C24”, las operaciones que se tendrían que hacer serían:
CL_COD=”C24”
Leer Dir. FCLIEN
Cuando se ejecutasen dichas órdenes, el sistema intentaría leer el registro cuyo contenido del campo clave fuera “C24”.
Se debe tener en cuenta que una operación de lectura secuencial siempre se realiza con éxito, ya que se limita a leer, en cada momento, el siguiente registro (salvo en la situación de final de fichero). Por el contrario, una operación de lectura directa puede no realizarse satisfactoriamente si el registro de clave dada no existe en el fichero.
Esta situación siempre es detectada por el sistema, por lo tanto, después de toda operación de lectura directa, se debe preguntar si el registro se ha encontrado o no para actuar en consecuencia.
Así por ejemplo, si en el fichero anterior deseáramos visualizar los datos del cliente “C24”, ante la posibilidad de que no existiese dicho registro en el fichero, se deberían especificar las siguientes operaciones:
CL_COD =”24”
Leer dir. FCLIEN
Si existe entonces
Visualizar “nombre:”, CL: NOM
Visualizar “dirección:”, CL_DIR
Visualizar “teléfono:”, CL_TEL
Si no
Visualizar “Cliente inexistente”
Fin_si
Escritura o grabación directa:
Esta operación consiste en escribir un nuevo registro en el fichero, es decir, realizar un alta sobre el mismo.
El sistema efectuará la grabación si la clave del nuevo registro no existía previamente en el fichero, en caso contrario, no la realizará. Por esta razón, al igual que en las lecturas directas, cuando se manda grabar un nuevo registro, se debe preguntar si ya existe o no, para tomar las medidas oportunas.
Por ejemplo, si queremos realizar un alta sobre el fichero FCLIEN, el pseudocódigo correspondiente sería:
Introducir CL_COD
Leer Dir. FCLIEN
Si no existe entonces
Introducir CL_NOM
Introducir CL_DIR
Introducir CL_TEL
Grabar Dir. En FCLIEN
Sino
Visualizar “Cliente ya existente”
Fin si
En este caso no es necesario preguntar la existencia del registro después de la operación de escritura directa, ya que sólo se manda la grabación cuando se ha comprobado su no existencia después de la orden de lectura.
Si se efectúan demasiadas altas sobre un fichero secuencial indexado, el área de excedentes contendrá muchos registros y la eficacia de esta organización disminuirá.
La mayoría de los sistemas operativos contienen programas de utilidades que reorganizan este tipo de ficheros, grabando todos sus registros en orden creciente de claves en el área primaria, actualizado simultáneamente el área de índices y creando el área de excedentes vacía. En caso de no disponer de dicha utilidad, habría que reorganizar el fichero mediante un programa de usuario.
Reescritura o regrabación directa:
La reescritura directa consiste en volver a escribir o grabar un registro, cuya clave ya existía previamente en el fichero, tras efectuar una o varias modificaciones sobre dicho registro. Se puede modificar cualquier campo del registro excepto el campo clave, ya que este campo identifica el registro.
El sistema sólo regrabará el registro si ya existía, si no fuese así, no efectuará la operación.
En general, como no se querrá modificar todos los campos del registro, es imprescindible realizar, previa a al regrabacion, una operación de lectura directa para tener toda la información del registro en la memoria principal. Si no se hace de esta forma, como lo que se intercambia entre la memoria central y la auxiliar no son campos individuales sino registros completos, aquellos campos en los que no se hayan introducido nuevos valores contendrán datos de operaciones anteriores, y al regrabar, se machacarán los contenidos correctos de los campos correspondientes del registro.
En los casos en que la regrabación se hace a continuación de una lectura directa, no es necesario preguntar después de la operación de reescritura si existe o no en el fichero un registro con esa clave, ya que, si dicha lectura se ha realizado satisfactoriamente, es obvio que el registro existe y por lo tanto, no hace falta comprobarlo más.
Por ejemplo si se quiere modificar el teléfono de un cliente “C24” del fichero anterior el pseudocódigo sería así:
CL_COD = “C24”
Leer Dir. FCLIEN
Si existe entonces
Introducir CL_TEL
Regrabar Dir. En FCLIEN
Sino
Visualizar “Cliente inexistente”
Fin si
En aquellas ocasiones en que se desease variar todos los campos de un registro (excepto el código), no haría falta efectuar una lectura previa, ya que en la propia memoria principal se introducirían datos en cada uno de los campos, y en el momento de la regrabación no importaría que estos machacasen la información del registro, dado que esto es precisamente lo que se quiere. En estos casos, si debe preguntarse después de una operación de reescritura directa si la clave existía o no, para tomar las medidas oportunas.
Si por ejemplo se pretendiese modificar todos los campos del cliente “C24”, el pseudocódigo sería así:
CL_COD = “C24”
Introducir CL_NOM
Introducir CL_DIR
Introducir CL_TEL
Regrabar Dir. En FCLIEN
Si no existe
Entonces
Visualizar “Cliente inexistente”
Fin si
Borrado directo:
Esta operación consiste en borrar un determinado registro del fichero.
Dicha operación se le indica al sistema introduciendo el valor de la clave del registro que se desea borrar en el campo clave y especificando, posteriormente, la instrucción de borrado directo.
Por ejemplo si se quisiera borrar el registro de clave “C24” del fichero FCLIEN, las instrucciones necesarias serían:
CL_COD = “24”
Borrar Dir. En FCLIEN
Esta operación sólo se llevaría a cabo si el registro de clave “C24” existiera en el fichero, si no fuese así, no se efectuaría. Por esta causa, después de una operación de borrado directo, siempre se debe preguntar por la existencia del registro para obrar en consecuencia.
El pseudocódigo correspondiente sería:
CL_COD = “C24”
borrar Dir. En FCLIEN
Si no existe entonces
Visualizar “Cliente inexistente”
Fin si
Al igual que en el caso de la reescritura, si se hubiese realizado una lectura previa del registro y ésta se hubiera efectuado satisfactoriamente, no sería necesario hacer la pregunta de existencia después de la operación de borrado.
11.6.-TRATAMIENTOS Y CREACION DE FICHEROS SECUENCIALES INDEXADOS
CREACION
En los ficheros secuenciales indexados los registros se graban físicamente en orden creciente de claves dentro del área primaria, si la creación se realiza con acceso directo, los registros de clave intermedia entre los ya existentes se enviarán al área de excedentes.
Si por el contrario, la creación se efectúa con acceso secuencial, y debido a que con este tipo de acceso no se permite la grabación de registros con clave intermedia, el área de excedentes permanecerá vacía.
Por esta razón es conveniente, a la hora de crear un fichero secuencial indexado, grabar mediante acceso secuencial sus registros en orden creciente de claves para que todos ellos se escriban dentro del área primaria.
La introducción de los campos de los registros se puede hacer bien desde el teclado o bien desde un fichero secuencial previamente ordenado por el campo, que será el campo clave del futuro fichero indexado.
El algoritmo consiste en una estructura repetitiva en la cual se irá leyendo un registro del fichero secuencial y grabándolo en el indexado. La condición de salida de dicha repetitiva será la finalización del fichero secuencial.
Ejemplo:
Un colegio guarda los datos de sus alumnos en un fichero secuencial, FALUM, con la siguiente descripción:
AL_COD | AL_NOM | AL_DIR | AL_TEL | AL_NOTA |
El fichero se supone ordenado ascendentemente por el campo AL_COD. Se desea crear el fichero secuencial indexado, FAL, con la siguiente descripción:
AM_COD | AM_NOM | AM_DIR | AM_TEL | AM_NOTA |
Su campo clave será AM_COD.
Aquellos registros que al intentar grabarlos provoquen un error debido a que sus claves sean duplicadas, se grabarán en otro dichero secuencial, FERROR, de descripción:
ER_COD | ER_NOM | ER_DIR | ER_TEL | ER_NOTA |
El pseudocódigo de este proceso sería:
Inicio
Abrir de entrada FALUM
Abrir de salida FAL
Abrir de salida FERROR
Leer FALUM
Mientras no fin FALUM
Mover campos de FALUM a FAL
Grabar sec. En FAL
Si error en grabación entonces
Mover campos de FALUM a FERROR
Grabar en FERROR
Fin si
Leer FALUM
Fin mientras
Cerrar FICHEROS
Fin
TRATAMIENTOS
Actualizacion o mantemimiento de un fichero secuencial indexado
Actualizar un fichero significa añadir al mismo los registros que sean altas, eliminar los que sean baja y modificar ciertos campos de algunos registros.
Para actualizar un fichero con organización secuencial se grababan, en un fichero secuencial de movimientos, las operaciones que debían realizarse sobre el maestro, y cada cierto periodo de tiempo se enfrentaban ambos dicheros para crear un nuevo maestro actualizado.
Cuando el fichero maestro tiene organización secuencial indexada, las actualizaciones se pueden realizar sobre el propio fichero, es decir, no es necesario crear un nuevo maestro, ya que:
Se le pueden añadir registros que irán al área de excedentes.
Se pueden modificar campos de sus registros volviendo a regrabar el registro sobre sí mismo.
Se pueden dar de baja registros. Esta operación la realiza el sistema poniendo una marca al registro correspondiente, de manera que lo deja inaccesible para su utilización, aunque no libera el hueco que ocupa en el fichero.
En el caso de ficheros maestros con organización secuencial indexada, no es necesario crear un fichero de movimientos con las actualizaciones, sino que si se desea, dichas actualizaciones se pueden efectuar desde el teclado según se vayan produciendo.
Actualización desde un fichero secuencial de movimientos(proceso batch)
Esta forma de actualización consiste en ir almacenando, en un fichero secuencial de movimientos, durante un determinado periodo de tiempo, todas las altas, bajas y modificaciones que se produzcan sobre los registros de un fichero secuencial indexado, para posteriormente actualizarlo. A este tipo de procesos se les denomina procesos batch o por lotes.
Los registros del fichero de movimientos contendrán los mismos campos que los registros del fichero maestro, además de un campo que indicará el tipo de movimiento que haya que realizar sobre el registro implicado. Entre sus campos estará un campo identificativo (clave) por el que se buscará el registro que se va a actualizar en el fichero indexado.
Se pueden utilizar dos formas de acceso al fichero indexado:
1. Si el fichero de movimientos está ordenado de forma ascendente por el campo identificativo, y el número de registros para actualizar del maestro es grande en comparación con el número de registros del fichero, puede ser conveniente tratar el fichero secuencial indexado como un secuencial.
2. Si el fichero de movimientos no está ordenado, o si el número de registros para actualizar es pequeño en comparación con el número de registros que el fichero maestro contiene, entonces la actualización se realiza leyendo secuencialmente el fichero de movimientos, accediendo directamente al fichero indexado por el campo identificativo, y realizando la operación de actualización correspondiente. Se deberán detectar, los posibles errores que puedan surgir para actuar del modo más correcto.
Ejemplo:
Se almacenan los datos de los artículos que comercializa un almacén en un fichero secuencial indexado, FARTI, con la siguiente descripción:
AR_COD | AR_NOM | AR_PRE | AR_TEL | AR_EXIS |
Donde AR_COD es la clave del fichero, AR_PRE el precio unitario y AR_EXIS las existencias. Se pretende actualizar este fichero desde un fichero secuencial, FMOVI, cuya descripción es:
MV_COD | MV_NOM | MV_PRE | MV_EXIS | MV_TIPO |
Donde MV_TIPO contendrá una A, una B o una M, según sea un alta, una baja o una modificación, respectivamente.
En el caso de una baja, el único campo que contendrá información será MV_COD.
En el caso de una modificación, solo contendrán información MV_COD y aquellos campos que van a modificar a los correspondientes del fichero FARTI, el resto estará a ceros o espacios, según sean campos numéricos o alfabéticos.
Durante la actualización, los registros erróneos se grabarán en el fichero secuencial FERROR, cuya descripción es la siguiente:
- El proceso consistirá en leer, registro a registro el fichero de movimientos FMOVI, y por cada registro leído, preguntar por el valor del campo MV_TIPO.
- Si MV_TIPO = "A", se moverán los campos de FMOVI a los correspondientes, del fichero FARTI y se dará una orden de grabación directa. Si esta orden no se puede ejecutar, es decir, si la clave del nuevo registro ya existe en FARTI, significa que es un registro erróneo y, por tanto, se moverán los campos de FMOVI a FERROR, así como un mensaje indicativo al campo ER_MEN y se grabará en FERROR.
- Si MV_TIPO = "B", se dará una orden de borrado directo sobre FARTI, y si la clave no existiera en FARTI (registro erroneo) , se procede a grabar en FERROR el registro correspondiente.
- Si MV_TIPO = "M", se leerá directamente en FARTI el registro que va a ser modificado con objeto de tener en memoria el contenido de todos sus campos, y así mantener con sus valores a aquellos que no vayan a ser modificados.
- Si no se efectúa lectura porque no existiera ningún registro con esa clave, se graba el registro de FMOVI en FERROR con el consiguiente campo mensaje.
- Si la lectura del registro se ha realizado con éxito, se pregunta a cada campo de FMOVI por su contenido. Si éste es distinto de espacios o cero, se mueve su valor al campo correspondiente de FARTI. Una vez finalizadas estas operaciones, se da una orden de reescritura sobre FARTI.
- Si MV_TIPO no es uno de los valores anteriores, se graba el registro en FERROR con el mensaje correspondiente.
- El pseudocódigo asociado sería:
PROCEDIMIENTO PRINCIPAL
INICIO
abrir de entrada/salida FARTI
abrir de entrada FMOVI
abrir de salida FERROR
leer FMOVI
mientras no fin FMOVI
si MV_TIPO= "A" entonces
<procedimiento alta>
si no
si MV_TIPO="B" entonces
<procedimiento baja>
si no
si MV_TIPO="M" entonces
<procedimiento modi>
si no
mover "error en tipo" a ER_MEN
<procedimiento error>
fin si
fin si
fin si
leer FMOVI
fin mientras
cerrar FICHEROS
FIN
PROCEDIMIENTO ALTA
INICIO
AR_COD = MV_COD
mover campos de FMOVI a FARTI
grabar dir. en FARTI
si ya existe entonces
mover "ya existe" a ER_MEN
<procedimiento error>
fin si
FIN
PROCEDIMIENTO BAJA
inicio
AR_COD = MV_COD
borrar dir. en FARTI
si no existe entonces
mover "baja imposible. No existe" a ER_MEN
<procedimiento error>
fin si
fin
PROCEDIMIENTO MODI
inicio
AR_COD = MV_COD
leer dir. FPARTI
si no existe entonces
mover "modificación imposible. No existe" a ER_MEN
<procedimiento error>
si no
si MV_NOM < > espacios entonces
AR_NOM = MV_NOM
fin si
si MV_PRE < > 0 entonces
AR_PRE = MV_PRE
fin si
si MV_EXIS < >0 entonces
AR_EXIS = MV_EXIS
fin si
regrabar dir. en FARTI
fin si
fin
PROCEDIMIENTO ERROR
inicio
mover campos de FMOVI a FERROR
grabar en FERROR
fin
Actualización desde el teclado(proceso on line)
En este tipo de actualizaciones, tanto las altas como las bajas y las modificaciones se realizan según se van rpoduciendo, sin que haya un periodo intermedio de recogida de las mismas para su posterior actualización sobre el fichero secuencial indexado.
Estos procesos se conocen con el nombre de "procesos on line", y siempre se efectúan de forma interactiva entre el operador y el ordenador.
Un programa de mantenimiento "on line" de un fichero secuencial indexado parte de un menú inicial, donde están reflejados todos los tipos de operaciones que se van a poder realizar: altas, bajas, modificaciones, etc.
En programación un menú es una lista de opciones que se visualizan por pantalla para permitir la selección de una de ellas.
Una vez elegida una determinada opción, el programa bifurcará a una rutina que desarrollará las operaciones específicas de dicha opción. Finalizada esta rutina, se retornará al menú por si el usuario desease seleccionar alguna otra. Todo menú debe tener una opción de salida del mismo que permita la finalización del programa.
El pseudocódigo asociado a un menú que permitiera la realización de altas si se teclea la letra "A", bajas si se teclea la letra "B", modificaciones si se teclea una "M" y que finalice si se pulsa una "F" , sería:
INICIO
abrir FICHEROS
OP_MENU = "S"
mientras OP_MENU < > "F"
visualizar "A . altas"
visualizar "B . bajas"
visualizar "M . modificaciones"
visualizar "F . finalizar"
visualizar "teclee opcion (A, B, M, F )"
introducir OP_MENU
si OP_MENU = "A" entonces
<procedimiento alta>
si no
si OP_MENU = "B" entonces
<procedimiento baja>
si no
si OP_MENU = "M" entonces
<procedimiento modi>
fin si
fin si
fin si
fin mientras
cerrar FICHEROS
FIN
En el pseudocódigo, OP_MENU es el nombre de una varialbe que guardará la opción elegida por el usuario, y <procedimiento alta>, <procedimiento baja> y <procedimiento modi>, son las encargadas de la realización de altas, bajas y modificaciones, respectivamente.
Proceso de alta:
La logica natural en un proceso de altas por teclado sería introducir los contenidos de todos los campos del nuevo registro, y a continuación mandar una orden de grabación directa sobre el fichero secuencial indexado.
Esta instrucción se ejecuta, si no existe en el fichero otro registro con la misma clave del nuevo. Se introduce el campo clave y con dicha clave, se realiza una lectura directa.
Si la lectura se realiza correctamente es que ya existe un registro con esa clave , y por lo tanto, en caso de una alta, esto sería un error, ( no puede darse de alta un artículo ya existente), y debería visualizarse un mensaje explicativo de dicho error.
Si, por el contrario la lectura no es satisfactoria, quiere decir que no existe ningún registro con dicha clave, y sólo en este caso, se permitiría la introducción del resto de los campos.
En este último caso, bastaría con dar una orden de grabación directa una vez finalizada la introducción de los campos restantes.
Si se selecciona la opción de modificación se volverá a permitir la introducción de los campos, despues de lo cual se preguntará de nuevo si se desea volver a modificar, anular o confirmar.
Si se elige la anulación, no se grabará el registro y se finalizará la rutina de alta.Si se opta por la confirmación se grabará el nuevo registro y se finalizará la rutina de altas.
El pseudocódigo asociado sería el siguiente:
PROCEDIMIENTO ALTA
inicio
Introducir AR_COD
leer dir. FARTI
si existe
entonces
visualizar "registro de clave", AR_COD, "ya existe"
si no
OP_ALTA = "M"
mientras OP_ALTA = "M" o "m"
introducir AR_NOM
introducir AR_PRE
introducir AR_EXIS
visualizar "M . modificar"
visualizar "A . anular"
visualizar "C . confirmar"
visualizar "teclee opcion (M, A, C )"
introducir OP_ALTA
mientras OP_ALTA <> ( "M" y "m" y "A" y "a" y "C" y “c")
introducir OP-ALTA
Fin mientras
fin mientras
si OP_ALTA = "C" o "c" entonces
grabar dir. en FARTI
fin si
fin si
fin
Como se observa en el pseudocódigo anterior, las instrucciones de introducción de los campos están dentro de un bucle, y se repetiran mientras que la opción elegida sea "M" (modificar). El bucle más interno es para asegurar que no se introduce una letra errónea.
Unicamente se saldrá de ambos bucles si se ha optado por la anulación (A) o la confirmación (C). Sólo en este último caso se grabará el registro.
El pseucódigo debe prever, además, la posibilidad de que se desee dar varias altas consecutivas, por tanto no es usual salir directamente de la rutina de altas cada vez que se efectúa una de ellas. Lo que se suele hacer es añadir al pseudocódigo las operaciones necesarias para que el programa, después de cada alta, pida la introducción de una nueva clave para comenzar con la siguiente. La rutina de las altas finalizará cuando se introduzca un determinado valor establecido (*) en lugar de una clave.
- El pseudocódigo ampliado en este sentido sería:
PROCEDIMIENTO ALTA
inicio
Introducir AR_COD
mientras AR_COD < > "*"
leer dir. FARTI
si existe entonces
visualizar "registro de clave", AR_COD, "ya existe"
si no
OP_ALTA = "M"
mientras OP_ALTA = "M" o "m"
introducir AR_NOM
introducir AR_PRE
introducir AR_EXIS
visualizar "(M)odificar (A)nular (C)onfirmar"
visualizar "teclee opcion (M, A, C )"
introducir OP_ALTA
mientras OP_ALTA <> ( "M" y "m" y "A" y "a" y "C" y "c")
introducir OP-ALTA
fin mientras
fin mientras
si OP_ALTA = "C" o "c" entonces
grabar dir. en FARTI
fin si
fin si
introducir AR_COD
fin mientras
fin
Proceso de baja:
La manera más sencilla de realizar una baja sobre un fichero secuencial indexado, desde el teclado, sería introducir el campo clave del registro que se desea dar de baja y dar una orden de borrado directo. Dicha orden se ejecutaría solo en el caso de que el registro con esa clave existiera en el fichero, si no, habría que visualizar un mensaje de error.
Se lee directamente el registro que se desea borrar y visualizar su contenido por pantalla. Una vez efectuadas estas operaciones, se pide conformidad de la baja, y sólo si la respuesta es afirmativa se lleva a cabo.
Para facilitar la posibilidad de realizar bajas consecutivas, toda la rutina estará dentro de una repetitiva que finalizará cuando se introduzca un "*" en el campo clave.
El pseudocódigo asociado sería:
PROCEDIMIENTO BAJA
inicio
Introducir AR_COD
mientras AR_COD < > "*"
leer dir. FARTI
si no existe entonces
visualizar "registro de clave", AR_COD, "no existe"
si no
visualizar AR_NOM
visualizar AR_PRE
visualizar AR_EXIS
visualizar " ¿ se confirma ( S/N )? "
introducir OP_BAJA
si OP_BAJA = "S" o "s" entonces
borrar dir. en FARTI
fin si
fin si
introducir AR_COD
fin mientras
fin
Proceso de modificaciones:
Este proceso consiste en introducir el campo clave del registro que se quiere modificar, leerlo de forma directa, visualizarlo por pantalla y permitir la modificación de sus campos tantas veces como se desee.
Al final de cada modificación se posibilitarán tres opciones diferentes: modificar de nuevo, anular la modificación o confirmarla.
Se utilizará una estructura de tipo mientras que se repetirá siempre que se elija la opción de vover a modificar y se saldrá de ella cuando se haya optado por la anulación o la confirmación.
En caso de confirmación, se regrabará de forma directa el registro.
El pseudocódigo asociado sería:
PROCEDIMIENTO MODIFICACION
inicio
Introducir AR_COD
mientras AR_COD < > "*"
leer dir. FARTI
si no existe entonces
visualizar "registro de clave", AR_COD, "no existe"
si no
OP_MODI = "M"
visualizar AR_NOM
visualizar AR_PRE
visualizar AR_EXIS
mientras OP_MODI = "M" o "m"
introducir AR_NOM
introducir AR_PRE
introducir AR_EXIS
visualizar "M . modificar"
visualizar "A . anular"
visualizar "C . confirmar"
visualizar "teclee opcion (M, A, C )"
introducir OP_MODI
mientras OP_ALTA <> ( "M" y "m" y "A" y "a" y "C" y "c")
introducir OP_MODI
fin mientras
fin mientras
si OP_MODI = "C" o "c" entonces
regrabar dir. en FARTI
fin si
fin si
introducir AR_COD
fin mientras
fin
Proceso de consulta:
Dentro del mantenimiento de un fichero secuencial indexado suele incluirse la opción de consultar un determinado registro por su campo clave, aunque en realidad, no es exactamente una operación de actualización.
El pseudocódigo sería el siguiente:
PROCEDIMIENTO CONSULTA
inicio
Introducir AR_COD
mientras AR_COD < > "*"
leer dir. FARTI
si no existe entonces
visualizar "registro de clave", AR_COD, "no existe"
si no
visualizar AR_NOM
visualizar AR_PRE
visualizar AR_EXIS
fin si
introducir AR_COD
fin mientras
fin
Otros procesos:
Es también usual incluir en el menú principal operaciones tales como listado completo del fichero, listado del fichero entre un rango de claves (listado entre límites, etc).
11.8.1- EJEMPLOS EN PSEUDOCÓDIGO:
INICIO
Abrir de
SALIDA FAGENDA
Introducir AG_NOM
AG_NOM <> “* “
FINAL
CERRAR FICHEROS
NO
SI
INTRODUCIR AG_DIR
INTRODUCIR AG_TEL
GRABAR EN
FAGENDA
INICIO
ABRIR DE
SALIDA
FAGENDA
CERRAR FICHEROS
AG_NOM<> “*”
FINAL
NO
SI
INTRODUCIR AG_DIR
INTRODUCIR AG_TEL
GRABAR EN FAGENDA
INTRODUCIR AG_NOM
Descargar
Enviado por: | Aarón Veredas |
Idioma: | castellano |
País: | España |