Ficheros – PRÁCTICA OBLIGATORIA Clases de Prácticas – 1ª sesión (1ª versión de la aplicación gestora) El material facilitado consta de: - Enunciado (especificaciones del problema) - Ficheros originales (fichero que resuelve las necesidades de información con un diseño bastante pobre, tanto a nivel lógico como físico). - Software de apoyo: o los ‘drivers’ del soporte que se va a utilizar o El interfaz de la aplicación - Documentación: guiones para casa una de las sesiones, plantillas de memorias intermedias (para la evaluación continua), y plantilla de la memoria completa (para el caso de optar por la evaluación normal) Objetivos generales: - Practicar el diseño de ficheros tipados en ambos niveles (lógico y físico) - Aumentar el conocimiento de manejo de ficheros desde el enfoque de los soportes (físico), con la gestión de bloque, buffers, y memorias intermedias. - Practicar el manejo de ficheros tipados desde el enfoque del usuario (lógico), con la gestión de registros: inserción, localización, selección, etc. - Asimilar las distintas organizaciones de ficheros estudiadas en la parte teórica de la asignatura (organizaciones base y auxiliares), así como de los distintos tipos de acceso, complementando ese estudio con la implementación de algunas de ellas. - Implementar un gestor que aplique las aproximaciones teóricas básicas (para organizaciones consecutivas) vistas en clase, haciendo especial hincapié en aquellas referidas al ahorro de espacio y a las organizaciones consecutivas. Planteamiento de Objetivos específicos: - Comprensión del punto de partida: organización, diseño (físico-lógico), etc. - Obtención de un diseño lógico optimizado (a partir de la descripción del diseño original obtenida en el análisis preliminar). - Obtención de un diseño físico-lógico optimizado (a partir del diseño lógico optimizado obtenido en el apartado anterior). - Implementación progresiva de una aplicación gestora, con las siguientes capacidades: o Interpretación del registro original o Inserción del registro optimizado o Importación (del archivo original al optimizado) o Recuperación condicional (búsqueda del primero y siguientes) o Navegación (del padre a los hijos, y viceversa) o Organización de un archivo basada en direccionamiento o Incorporación de organizaciones auxiliares para reducir el número de accesos o Acceso invertido a la información - Opcionalmente, se podrán desarrollar otras funcionalidades: borrar y modificar registros, navegación entre registros padre-hijo virtual en sentido opuesto al implementado en la parte obligatoria, operaciones de mantenimiento (compactación, reordenación, reorganización), organizaciones de archivo de complejidad superior a aquellas requeridas en el enunciado, etc. Pasos a dar para realizar la primera sección de la primera práctica Análisis Preliminar: (análisis del sistema actual e ingeniería inversa). La descripción del diseño lógico original proporcionado (enunciado) contiene un número no definido de erratas. Para localizarlas, y obtener así los diseños lógico y físico-lógico originales, se deberá realizar un análisis directo del fichero original (ingeniería inversa sobre el fichero de caracteres, que podrá llevarse a cabo con la ayuda de cualquier editor de texto como, por ejemplo, el notepad® de Windows®). Para facilitar este estudio, puede ser interesante aislar un registro y almacenarlo en un fichero aparte (copiarlo con el notepad sobre un fichero de texto nuevo y vacío). A partir de este estudio, se tendrá que describir en primer lugar el diseño físico-lógico de la organización original, utilizando para ello la notación vista en clase. En segundo lugar, partiendo de ese diseño físico-lógico, se tendrá que descubrir el diseño lógico que le dio lugar (similar al proporcionado en el enunciado, pero con los errores de descripción corregidos). En este diseño habrá que señalar las deficiencias semánticas y plantear soluciones para cada una. Diseño Optimizado: A partir del diseño lógico (que describe el registro original) obtenido en el análisis preliminar, se realizará un nuevo diseño lógico optimizado del registro (nuevo archivo) que subsane las deficiencias (de diseño) que contenga (a juicio de cada grupo de prácticas). Durante esta fase se eliminarán campos redundantes, se dividirá un campo en varios, se fusionarán varios campos en uno solo o, si fuera necesario añadir alguna información no contemplada, se añadirán los campos que se requieran. Posteriormente, a partir de este diseño lógico optimizado, se realizará el diseño físico-lógico optimizado. Este diseño procurará describir el registro según será almacenado en el nuevo fichero, teniendo en cuenta que el objetivo principal es, en este caso, minimizar el espacio necesario para el almacenamiento de los registros. En esta tarea, se deberán aplicar las técnicas vistas en clase de teoría (introducción de marcas y codificación). No se permitirá trabajar a nivel de bit con los campos (un byte sólo puede pertenecer a un campo). Si se podrá, por otro lado, utilizar marcas de tipo mapa y realizar cabeceras con marcas a nivel de bit. Preparación para la Implementación de la aplicación gestora Además de los diseños expuestos, en esta primera sesión de prácticas se han de implementar los métodos necesarios para leer los registros del fichero original. Ya se han examinado ese fichero y su organización, con lo que se está en disposición de interpretar su contenido (se tiene su diseño físico-lógico). Este código se implementará dentro del método ‘importar’ de la aplicación gestora (clase ‘GestorDeFicheros.java’). Esta clase está contenida, entre otras, en el paquete de Sw básico para la realización de las prácticas de Ficheros que se facilita a los grupos, y que se ejecutará sobre el entorno de ejecución 1.5.0 (jsdk 1.5.0). El primer paso es descargarse este software, compilarlo y ejecutarlo para acostumbrarse a su funcionamiento. A continuación, se analizará el paquete proporcionado para asimilar su estructura, haciendo especial hincapié en las clases ‘GestorDeFicheros.java’ y ‘Esquema.java’ que son las que tendrán que modificarse durante la realización de estas prácticas. Además se proporcionan dos ficheros java extra (‘EjemploUsoFicheroSerial.java’ y ‘EjemploUsoMemoriaInetrmedia.java’) con los cuales se podrá ver a modo de ejemplo como funciona la lectura de ficheros así como la memoria intermedia, por lo que es recomendable verlas en esta sesión. El siguiente diagrama muestra los módulos de que consta: Memoria Intermedia Driver Direccionado buffer abrir_fichero cerrar_fichero guardar_fichero leer escribir abrir cerrar reset leer escribir limpiar copiar esquema Aplicación_Serial Driver Serial abrir cerrar reset leer escribir abrir_archivo cerrar_archivo guardar_archivo importar buscar siguiente ... insertar irPadre ... acceso_invertido salir Interfaz Como ya se ha mencionado, la primera tarea consiste en leer un registro del fichero original mediante el driver serial. Haciendo uso de los métodos que proporciona, se deberá abrir el fichero, leer un registro, y mostrarlo por pantalla (consola java). Este código se ubicará en el método ‘importar’ y será invocado al pulsar el botón correspondiente en la interfaz proporcionada. Finalmente, se ampliará este código para que muestre un registro, espere a que el usuario pulse una tecla, muestre el siguiente registro,..., y así sucesivamente hasta llegar al final del fichero (reconocido por la marca de fin de fichero), de lo que se informará al usuario antes de terminar. Para la implementación de este método, se podrá contar con una variable ‘bufferE’ que representa un físico de lectura (1024 caracteres, es decir, un bloque). En él se podrá mantener el último bloque leído desde el dispositivo. Este buffer será recorrido carácter a carácter para extraer el primer registro lógico, y luego el siguiente, y así sucesivamente hasta el final. En definitiva, se trata de aplicar el siguiente algoritmo: [ declarar una variable de tipo bloque, y un contador (número de 0 a 1023) ] 0. reset; Leer un bloque sobre el buffer (físico) de E/S (un bloque) Inicializar puntero a carácter sobre el buffer (cont = 0) 1. Leer un registro lógico del bloque, desde el carácter cont-ésimo. Para ello, cada campo debe pasarse desde el buffer E/S al buffer del interfaz (lógico): a. Hasta que se hayan leído todos los campos, leer sgte. campo • Hasta leer todos los car. del campo actual, leer sgte. carácter i. Si fin de bloque (cont > 1023), leer otro bloque sobre el buffer (físico) e inicializar cont ii. Leer carácter(cont), e incrementar cont iii. Si aún no se ha leído todo el campo, volver al paso (i) b. Escribir el campo en el buffer del interfaz (de la aplicación) c. Si quedan elementos de datos por leer, volver al paso (a) 2. Escribir el registro por pantalla, junto con el corresp. mensaje de estado. 3. Si quedan registros, esperar confirmación, y volver al paso 1 4. Fin (informar mediante un mensaje estado). Notas: - Si se quiere contemplar que el fichero abierto no contenga ningún registro, la operación de buscar implementaría, en realidad, los pasos: 0, 3, 4 y 1. - Observar la diferencia entre un buffer del “lado físico” (soportes) y un buffer del “lado lógico” (interfaz de usuario).