clase 3 estructura de datos filas
DESCRIPTION
ing de sistemasTRANSCRIPT
Estructura De Estructura De DatosDatos
Docente: Carlos A. Ruiz De La Cruz MeloCorreo: [email protected]
ALGORITMICA IIIALGORITMICA III
OPERACIÓN OPERACIÓN ELEMENTALELEMENTAL
OE es aquella cuyo tiempo de ejecución se puede acotar superiormente por una constante, que depende de la implementación en particular.
El análisis algorítmico dependerá del número de operaciones elementales ejecutadas, más no nos preocupará el tiempo empleado por dicha operación elemental, en una determinada implementación particular.
OPERACIÓN OPERACIÓN ELEMENTALELEMENTAL
Es posible distinguir entre los tiempos de ejecución de las diferentes operaciones elementales, lo cual es necesario a veces por las características específicas del ordenador (por ejemplo, se podría considerar que las operaciones + y ÷ presentan complejidadesdiferentes debido a su implementación). Sin embargo, para esta asignatura supondremos que sus tiempos de ejecución son todos iguales.
CRITERIOS PARA DEFINIR LA CRITERIOS PARA DEFINIR LA COMPLEJIDAD COMPLEJIDAD
Existen dos criterios para definir la complejidad:
1. Criterio de Costo Uniforme
2. Criterio de Costo logarítmico
En el que cada instrucción RAM requiere una unidad de tiempo para ejecutarse y cada registro requiere una unidad de espacio.
Tiene en cuenta que una palabra de memoria tiene una capacidad de almacenamiento limitada
COSTO UNIFORMECOSTO UNIFORME
Asume que cada instrucción de la maquina es ejecutada en una unidad de tiempo.
Por este criterio, se asume un numero de instrucciones ejecutadas por el computador y una cantidad de registros de memoria utilizados.
En dicho caso el tiempo de ejecución del algoritmo estará dado por el número de operaciones que se ejecuta.
Este criterio conduce a valores aproximados y solo es recomendable para obtener una primera aproximación de indicadores de complejidad
PROGRAMAS Y DATOS DEL SISTEMA OPERATIVO
PROGRAMA DE USUARIO
DATOS DEL PROGRAMA DE USUARIO
LIBRE
COSTO UNIFORMECOSTO UNIFORMEMEMORIA RAM
instrucción 1instrucción 2instrucción 3:instrucción N
AX, BX
Almacenan los datos que son utilizados por las instrucciones de maquina
Aparecen como operando en las instrucciones
mov AX, 20 mueve 20 a axmov BX, 5 mueve 5 a bxadd AX, BX suma bx a ax y deja el resultado en ax
Registros de datos
Criterios para definir la Criterios para definir la Complejidad Complejidad
Criterio de Costo Logarítmico:
Tiene en cuenta que una palabra de memoria tiene una capacidad de almacenamiento limitada (número de bits necesario para codificar los datos).
El número de bits o dígitos necesario para representar un número entero a esta dado por:
El costo de ejecutar una sentencia de programa será proporcional a esta cifra
01
01log)(ω 2
a
Zaaa
CRITERIO DE COSTO CRITERIO DE COSTO LOGARÍTMICOLOGARÍTMICO
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
65 535
bit
byte byte
PERSISTENCIA
Capacidad para conseguir que los datos sobrevivan a la ejecución del proceso que los creo, de forma que puedan ser reutilizados en otro proceso.
Se entiende por persistencia en la programación orientada a objetos como la capacidad que tienen los objetos de conservar su estado e identidad entre distintas ejecuciones del programa que los creó o de otros programas que accedan a ellos.
La persistencia no es ni una capacidad ni una propiedad de la POO, no tiene nada que ver con el paradigma en sí, solo es el mecanismo que se usa para persistir información de un determinado tipo (como puede ser serializar, guardar los datos en una tabla, en un archivo plano, etc).
Persistencia como mecanismo
Los objetos para la persistencia
Una instancia persistente es aquella cuyos datos perduran a la ejecución del proceso que materializo la instancia.
Una instancia transitoria es toda instancia cuyos datos desaparecen cuando finalizan los procesos que la manipulan
Objetivos de la persistencia
La persistencia permite al programador almacenar, transferir y recuperar el estado de los objetos. Para esto existen varias técnicas:
SerializacionMotores de persistenciaBases de datos orientadas a objetos
Un archivo o fichero de datos es una colección de registros relacionados entre si con aspectos en común y organizados para un propósito especifico.
Un archivo en una computadora es una estructura diseñada para contener datos, estos están organizados de tal modo que puedan ser recuperados fácilmente, actualizados o borrados y almacenados de nuevo en el archivo con todos los cambios realizados
ARCHIVOS/FILASARCHIVOS/FILAS
Este tema se centra en el uso de los archivos como flujos de datos de un programa, tanto de entrada, para proporcionar los datos necesarios para realizar la tarea que ejecuta el programa, como de salida, para almacenar los datos obtenidos por el programa.
Se puede considerar un flujo como una secuencia de caracteres.
ARCHIVOS/FILASARCHIVOS/FILAS
Todos los datos fluyen a través del ordenador desde una entrada hacia una salida.
Este flujo de datos se denomina también stream.
Hay un flujo de entrada (input stream) que manda los datos desde el exterior (normalmente el teclado) del ordenador, y un flujo de salida (output stream) que dirige los datos hacia los dispositivos de salida (la pantalla o un archivo).
FLUJOS
El proceso para leer o escribir datos consta de tres pasos Abrir el flujo de datos Mientras exista más información (leer o escribir ) los datos Cerrar el flujo de datos
ORGANIZACIONORGANIZACION
Organización secuencial Organización directa Organización indexada
La organización de un archivo define la forma en la que los registros se disponen sobre el soporte de almacenamiento, o también se define la organización como la forma en que se estructuran los datos en un archivo. En general, se consideran tres organizaciones fundamentales:
MEMORIA PRIMARIA
MEMORIA SECUNDARIA
APLICACIÓNAPLICACIÓN
Archivos DISCO
0 1 2 3
Listas
Arreglos
ARCHIVO EN C++ O EN JAVA
Para C++ es un dispositivo externo hacia/desde el cual puede fluir información.
micrófono
Cinta magnética
impresora
Disco duro
Archivos binarios / texto
Tipo de archivo que se usara para filas secuenciales
ARCHIVO BINARIO/TEXTOARCHIVO BINARIO/TEXTO
Almacenamientoen archivo
texto
Binario
Almacena caracteres ASCII
Visible por un editor
Almacena en hexadecimal
No visible por cualquier editor
Dividido en segmentos
ARCHIVO BINARIOARCHIVO BINARIO
REGISTRO 1
REGISTRO 2
REGISTRO N-1
REGISTRO N
:
EOF
Dividido en segmentos de igual tamaño
Marca de fin de archivo (End of File)
Estructura de un archivo binario
UBICACIÓN LÓGICA Y FÍSICAUBICACIÓN LÓGICA Y FÍSICA
CODIGO NOMBRE NOTA
90021 Carlos Rojas Sánchez 10
89765 Manuel Ventura Díaz 11
78560 Ana Alvarado Gálvez 15
lógica física
0 0
1 56
2 112
Especificación ALUMNO variables entero : código cadena: nombre real : nota operaciones significadoFin_ALUMNO
En C++Suponemos quecódigo, nombre y nota suma en total 56 bytes
ACCESO AL DISCO ACCESO AL DISCO
Para empezar, los discos distribuyen los datos en dos o tres dimensiones. Las cabezas de lectura/escritura se mueven a lo largo del radio del disco, a distancias preestablecidas. Cada una de esas distancias define una pista
A su vez, cada pista está dividida en partes más pequeñas, llamadas sectores.
cada disco está compuesto en realidad por varios discos llamados platos, cada plato tiene dos caras, y en cada cara se coloca una cabeza de lectura/escritura.
De modo que para acceder a un dato será necesario calcular en qué plato, pista y sector está almacenado, mover la cabeza a la pista adecuada y esperar a que el sector pase por debajo de la cabeza correspondiente al plato indicado
La unidad mínima que se puede leer o escribir en un disco es un sector. El tamaño del sector es variable, generalmente son de 512 bytes, pero pueden ser diferentes.
El sistema operativo no trabaja directamente con sectores, sino con clusters. Cada cluster tiene un número entero de sectores.
Una velocidad de 5400RPM permitirá una transferencia entre 10MB y 16MB por segundo con los datos que están en la parte exterior del cilindro o plato, algo menos en el interior.
Aún cuando los microprocesadores utilizados en los discos duros son relativamente poderosos, las tareas asignadas a ellos toman tiempo en llevarse a cabo. En promedio, este tiempo está en el rango de los .003 milisegundos.
ACCESO AL DISCO ACCESO AL DISCO
ORGANIZACIÓN SECUENCIALORGANIZACIÓN SECUENCIALLa Fila secuencial es una estructura de datos lineal en la cual los elementos están dispuestos uno tras de otro, de tal modo que en las operaciones para manipular los elementos se respeta la secuencia de los mismos en la estructura.
Registro 1
Registro 1
:
Registro 1
:
Registro N-1
Registro N
Inicio de archivo
fin de archivo
ORGANIZACIÓN SECUENCIALORGANIZACIÓN SECUENCIAL Accesar el próximo registro es trivial.
Para agregar registros a un archivo secuencial hay dos opciones: Crear un nuevo archivo. Agregar al final del archivo.
Para eliminar los registros estos se pueden marcar (necesidad de un campo extra) o se debe crear un nuevo archivo.
Los archivos secuenciales ocupan un tamaño mínimo, o sea, sólo el espacio requerido para el almacenamiento de los registros.
ORGANIZACIÓN DIRECTAORGANIZACIÓN DIRECTA
Los datos se colocan y se acceden aleatoriamente mediante su posición, es decir, indicando el lugar relativo que ocupan dentro del conjunto de posiciones posibles.
En esta organización se pueden leer y escribir registros, en cualquier orden y en cualquier lugar.
Ventaja
Rapidez de acceso a un registro cualquiera
Desventajas
Establecer la relación entre la posición que ocupa un registro y su contenido;Puede desaprovecharse parte del espacio destinado al archivo
ORGANIZACIÓN DIRECTAORGANIZACIÓN DIRECTA
ORGANIZACIÓN INDEXADAORGANIZACIÓN INDEXADA
Un archivo con esta organización consta de dos áreas:
Archivo de índicesArchivo de datos
CLAVE DIRECCION
234 010
345 020
422 030
467 040
: :
678 090
CLAVE DATOS
010 234
011 234
:
019 234
020 345
021 345
:
029 345
030 422
:
039 422
AREA DE INDICES
AREA DE DATOS
ORGANIZACIÓN INDEXADAORGANIZACIÓN INDEXADA
# Razón fecha Dir.
01 A 01/01/11 0
02 B 02/05/12 342
08 C 14/07/12 570
010 D 20/09/12 684
# Cod. Descrip. Pu cant
01 11 P 2 10
01 18 Q 1 20
01 01 M 3 5
02 09 Y 4.5 3
02 11 P 2 15
08 01 M 3 4
010 03 W 0.5 30
01- Razon: AFecha: 01/01/11
cod Descrip PU CANT
11 P 2 10
18 Q 1 20
01 M 3 5
Fila de INDICE
Fila de DATO
0
342
570
684
Dirección física
Cada objeto de fila DATOS tiene 114 bytes
ORGANIZACIÓN INDEXADAORGANIZACIÓN INDEXADA
VentajaRápido acceso, y, además, el sistema se encarga de relacionar la posición de cada registro con su contenido por medio del área de índices.Gestiona las áreas de índices y excedentes.
DesventajasNecesidad de espacio adicional para el área de índices.El desaprovechamiento de espacio que resulta al quedar huecos intermedios libres después de sucesivas actualizaciones.
Se pueden considerar tres criterios básicos:
Rápido AccesoEconomía de AlmacenamientoFacilidad de Uso
CRITERIOS PARA ELEGIR UN CRITERIOS PARA ELEGIR UN TIPO DE ORGANIZACIÓNTIPO DE ORGANIZACIÓN
La elección de la organización determina el rendimiento relativo del sistema para cada una de las tres características enunciadas:
ALGUNAS MEDIDAS DE ALGUNAS MEDIDAS DE RENDIMIENTO RENDIMIENTO
Almacenamiento requerido por un registro.
Tiempo de búsqueda de un registro. Tiempo requerido para leer todo el
archivo. Tiempo requerido para insertar un
registro. Tiempo para modificar un registro.
Rápido Acceso Economía de
Almacenamiento Facilidad de Uso
PRIMITIVASPRIMITIVAS
inicio( F )
Para F : identificador de fila/archivo/fichero v : variable del mismo tipo de dato que almacena la fila
Posiciona el cabezal de lectura de la fila F al inicio
leer ( F , v ) Coloca en v el contenido de un registro de la fila F
escribir ( F , v )Coloca al final de la fila F el contenido de v
último ( F )Retorna falso si no es final de fila F de lo contrario retorna verdadero
cerrar ( F ) cierra la fila F
ubicar( F, p ) Se ubica en una posición p de la fila F
comprimir( F, p ) Escribe una cantidad de objetos P en la fila F
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces
mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0344 Juan
0944 Ana
0723 Jorge
Encontrar primero código
0344
k = i
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0344 Juan
0944 Ana
0723 Jorge
ki
Se elimino el código
0344
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0944 Ana
0944 Ana
0723 Jorge
ki
Se elimino el código
0344
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0944 Ana
0944 Ana
0723 Jorgeki
Se elimino el código
0344
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0944 Ana
0723 Jorge
0723 Jorgeki
Se elimino el código
0344
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0944 Ana
0723 Jorge
0723 Jorgeki
Se elimino el código
0344
function eliminar(): entero ALUMNO: a,p entero: i, i0 condfalso salirverdadero inicio(base) leer( cod) leer(base, a) mientras no ultimo(base) y salir hacer
si (a.codigo=cod) entonces condverdadero salirfalso sino
ii+1 finsi
leer(base, a) finmientras ki salirverdadero si(cond = verdadero) entonces mientras(salir=verdadero) hacer kk+1
ubicar(base,k) leer(base,p) si (no ultimo(base)) entonces
ubicar(base, i) escribir(base, p) ii+1
sino cerrar(base) inicio(base) comprimir(base, i) cerrar(base)
salirfalso finsi finmientras
sino cerrar(base) finsi fineliminar
ORGANIZACIÓN ORGANIZACIÓN DIRECTADIRECTA
código nombre
0123 Carlos
0856 María
0944 Ana
0723 Jorge
Se elimino el código
0344
i
PERSISTENCIA EN C++PERSISTENCIA EN C++ARCHIVOSPosible en C++ código nombre edad
01 Juan 20
04 María 18
class PERSONA{ int codigo; String nombre; int edad }
código nombre credito
01112 Estadística 4
04023 Matemática I 4
08999 Algoritmica 3
código nombre edad categoria
0177 Guerra 20 Auxiliar
0409 Pablo 18 asociado
class ASIGNATURA{ int codigo; String nombre; int credito }
class DOCENTE{ int codigo; String nombre; int edad; String categoria ASIGNATURA curso[5] ;}
ASIG
NA
TU
RA
DO
CEN
TE
No es Posible en C++
MANEJO DE FILAS EN CMANEJO DE FILAS EN CActualmente existen tres formas para manejar los archivos en lenguaje C, entre los dos primeros, uno llamado de primer nivel (también llamado secuencial) y otro llamado de segundo nivel (también llamado tipo registro o de alto nivel).
1. En el nivel más bajo se considera el archivo como un conjunto de bytes continuos, esto sin tener en cuenta como se han grabado, un usuario puede leer la cantidad de bytes que desee no importando la posición en la cual se encuentren éstos.
2. En el modo de más alto nivel se puede acceder a uno o varios registros, es decir, lo que se lee cada vez es una agrupación lógica. Las operaciones de primer nivel, como se las llama a las de nivel más bajo, son las más potentes. Se dice que estas operaciones son las primitivas del sistema: son las operaciones básicas. Las de segundo nivel se construyen a partir de éstas.
La siguiente tabla muestra las instrucciones de primer nivel para manejo de archivos. Todas estas funciones se encuentran definidas en el archivo io.h.
INSTRUCCIONES A BAJO NIVELINSTRUCCIONES A BAJO NIVEL
read() Lee un buffer de datos write() Escribe un buffer de datos open() Abre un archivo en disco close() Cierra un archivo lseek() Busca un byte especificado unlink() Elimina un archivo del directorio
0x01 Sólo Lectura O_RDONLY 0x02 Sólo Escritura O_WRONLY 0x04 Lectura/Escritura O_RDWR
Modos de acceso al archivo:
#include <stdio.h>#include <stdio.h>#include <io.h>#include <io.h>void main() {void main() {
int f, modo=0x01;int f, modo=0x01;if( (f= open("Nombre1", modo))==-1){if( (f= open("Nombre1", modo))==-1){ printf("NO se puede abrir ! ");printf("NO se puede abrir ! ");}}
}}
INSTRUCCIONES A BAJO NIVELINSTRUCCIONES A BAJO NIVELPara este ejemplo el archivo NOMBRE1 debe existir. Si NO existe la función open devuelve -1
#include <stdio.h>#include <io.h>#include <fcntl.h>void main(){ int f, modo=0x04; /* Se puede usar O_RDWR en vez de modo */ if( (f= open("Nombre1", modo|O_CREAT))==-1) {
printf("NO se puede abrir ! "); } else printf(" Archivo Abierto !");
}
Si el archivo NO existe lo crea. El acceso será de lectura-escritura. Todo lo que escriba en el archivo borrará la información existente. Si el modo es O_RDONLY, sólo se podrá leer
INSTRUCCIONES A BAJO NIVELINSTRUCCIONES A BAJO NIVEL
Lectura de archivosLectura de archivos
int read(int fn, char *buf,int nbytes);
Escritura de archivosEscritura de archivos
int write(int fn,char *buf,int nbytes);
Posicionamiento de un archivoPosicionamiento de un archivo
long lseek(int fn, long desp1,int modo);
Cierre de archivosCierre de archivos
int close(int fn);Modo Descripción
0 Principio del archivo
1 Posición actual en el archivo
2 Al final del archivo
INSTRUCCIONES DE SEGUNDO INSTRUCCIONES DE SEGUNDO NIVELNIVELEn las instrucciones de segundo nivel los archivos ya no se designan por un número, sino, por un puntero a una estructura compleja llamada FILE cuya descripción se haya en el archivo stdio.h.
Apertura de archivoApertura de archivo
FILE *fopen(char *nombrefich, char *modo);
Modo Descripción
"r" Para lectura solamente
"w" Para escritura solamente (si el archivo ya existiera lo borra)
"a" Añadir al final de un archivo que ya existe.
"r+" Actualizar uno que ya existe
Lectura de archivoLectura de archivoint fread(char *p,int s,int n, FILE *fp);
Escritura de archivoEscritura de archivofwrite(char *p,int s,int n, FILE *fp);
Cerrar archivoCerrar archivoint fclose(FILE *fp);
Posicionamiento en un archivoPosicionamiento en un archivofseek(FILE *fp, long pos, int modo); /* Análoga a lseek */
Condición de fin de archivoCondición de fin de archivoint feof(FILE *fp);
Posicionamiento al comienzo de un archivoPosicionamiento al comienzo de un archivorewind(FILE *fp);
INSTRUCCIONES DE SEGUNDO INSTRUCCIONES DE SEGUNDO NIVELNIVEL
MANEJO DE FILAS EN C++MANEJO DE FILAS EN C++
En C++, se utilizan streams (flujos) para gestionar la lectura y escritura de datos. Ya conocemos dos flujos estándar: cin y cout.
En definitiva, abrir un fichero significa definir un stream. Dicho stream permite la transferencia de datos entre el programa y el fichero en disco
El buffer es un área de memoria situada en la RAM asignada al programa que abre el archivo
MANEJO DE FILAS EN C++MANEJO DE FILAS EN C++ Toda transferencia de datos entre el programa
y el fichero en disco se realiza a través del buffer. El buffer está para dar eficiencia.
Las operaciones de E/S son más eficientes:
El acceso a la memoria RAM consume menos tiempo que el acceso a un dispositivo físico.
El buffer hace que el número de accesos al fichero físico sea menor.
El uso del buffer permite realizar operaciones de entrada salida de forma más eficiente.
Para poder manipular archivos, C++ dispone de la biblioteca estandar fstream (file stream) donde se encuentran todas las funciones necesarias para abrir y cerrar archivos, así como para realizar las operaciones de lectura y escritura de datos en archivos.
MANEJO DE FILAS EN C++MANEJO DE FILAS EN C++
C++ provee las siguientes clases para realizar operaciones de entrada y salida de carácteres hacia o desde archivos:
ofstream: El flujo para escribir archivos. ifstream: El flujo para leer archivos. fstream: Flujo de lectura/escritura sobre archivos
#include <conio.h>#include <iostream.h>#include <fstream.h>class ENTERO{ int num; public: void REGISTRAR(int x){ ofstream esc("ejemplo1",ios::app| ios::binary); if(!esc){ cout<<"archivos on problemas";getch(); } else{ esc.write(reinterpret_cast<char *>(&x),sizeof(ENTERO)); esc.close(); } } void MOSTRAR(){ int y; ifstream lec("ejemplo1"); if(!lec){ cout<<"archivos con problemas";getch(); } else { lec.read(reinterpret_cast<char *>(&y),sizeof(ENTERO)); while(!lec.eof()){ cout<<"\n"<<y; lec.read(reinterpret_cast<char *>(&y),sizeof(ENTERO)); } lec.close(); } }};
int main(){ char op; int dato; ENTERO e; for(;;){ cout<<" \n adicionar <1>"; cout<<" \n Mostrar <2>"; cout<<" \n salir <3>"; op=getch(); switch(op){ case '1':cout<<"\n Ing entero :";cin>>dato; e.REGISTRAR(dato);break; case '2':e.MOSTRAR();getch(); break; case '3':return 0; } }}
PROGRAMA DE FILAS EN C++PROGRAMA DE FILAS EN C++
PERSISTENCIA EN JAVA
Si bien pudieran encontrarse otros mecanismos alternativos, es posible que resultaran problemáticos y dieran lugar a errores, e incluso podrían llegar a complicarse si se necesitara realizar un seguimiento de la jerarquía de los objetos.
En el caso en el que se debiera escribir una aplicación para una gran empresa que contenga varios miles de objetos y se tuviera que escribir código para guardar en un disco y recuperar desde éste los campos y propiedades para cada objeto, la serialización proporcionaría el mecanismo adecuado para conseguir este objetivo con el mínimo esfuerzo.
PERSISTENCIA EN JAVAARCHIVOS
código nombre edad
01 Juan 20
04 María 18
class PERSONA{ int codigo; String nombre; int edad }
SERIALIZACION
código nombre credito
01112 Estadística 4
04023 Matemática I 4
08999 Algoritmica 3
código nombre edad categoria
0177 Guerra 20 Auxiliar
0409 Pablo 18 asociado
class ASIGNATURA{ int codigo; String nombre; int credito }
class DOCENTE{ int codigo; String nombre; int edad; String categoria ASIGNATURA curso[] = new ASIGNATURA[5];}
ASIG
NA
TU
RA
DO
CEN
TE
No es Posible en C++ pero si en java
Podemos abrir un fichero de texto para leer usando la clase FileReader. Esta clase tiene métodos que nos permiten leer caracteres. Sin embargo, suele ser habitual querer las líneas completas, bien porque nos interesa la línea completa, bien para poder analizarla luego y extraer campos de ella. FileReader no contiene métodos que nos permitan leer líneas completas, pero sí BufferedReader. Afortunadamente, podemos construir un BufferedReader a partir del FileReader.
Para escribir en un archivo de texto lo primero que tendremos que hacer será crear un BufferedWriter. Esta clase nos ayuda a manejar los stream en forma de buffer con métodos muy sencillos. Este buffer necesitará saber cual es el fichero. Esto se lo proporcionamos desde la clase FileWriter
USANDO ARCHIVOS DE TEXTO
Usando archivos de texto
import java.io.*;import java.lang.*;import java.util.*;class TEXTO{ PrintStream p=new PrintStream(System.out); BufferedReader b=new BufferedReader(new InputStreamReader(System.in)); String nombre; String dato(String mensaje){ System.out.print(mensaje); try{ nombre=b.readLine( ); } catch(IOException ioe){ p.println("No se puede leer"); } return nombre; }
public void escritura(String nomb){ String arch = "prueba.dat"; try{ FileWriter fw = new FileWriter ("text.txt",true); BufferedWriter bw = new BufferedWriter (fw); PrintWriter salArch = new PrintWriter (bw); salArch.println(nomb); salArch.close(); } catch(java.io.IOException ioex){ } }
Metodo para escribir en un archivo de texto
public void mostrar(){ try { FileReader fr=new FileReader("text.txt"); BufferedReader entrada=new BufferedReader(fr); String s; while((s=entrada.readLine( ) )!=null){ System.out.println("Salida del archivo : "+s); } entrada.close(); } catch(java.io.FileNotFoundException fnfex){ } catch(java.io.IOException ioex){ } }
public static void main(String arg[ ]){ TEXTO fun= new TEXTO(); fun.escritura(fun.dato("Ingrese algo al archivo > ")); fun.mostrar(); } }
Usando archivos de texto
Metodo para visualizar la informacion de un archivo de texto
La clase DataOutputStream, es una extensión de la clase OutputStream, y añade a ésta última la posibilidad de escribir tipos de datos primitivos, pero no restringidos únicamente a bytes y a matrices de bytes, como en el caso de OutputStream.
Mediante la clase DataOutputStream podemos escribir datos de tipo int, float, double, char, etc.
La clase DataInputStream está diseñada para leer datos generados por un objeto DataOutputStream. La especificación de esta clase garantiza que cualquier archivo escrito por un DataOutputStream, sobre cualquier plataforma y sistema operativo, será legible correctamente por un DataInputStream.
USANDO ARCHIVOS BINARIOS
Usando archivos binariosimport java.io.*;import java.lang.*;import java.util.*;class BINARIO{ PrintStream p=new PrintStream(System.out); BufferedReader b=new BufferedReader(new InputStreamReader(System.in)); String nombre; public String dato(String mensaje){ System.out.print(mensaje); try{ nombre=b.readLine( ); } catch(IOException ioe){ p.println("No se puede leer");
} return nombre; }
public void escritura(double d1){ try{ DataOutputStream dos= new DataOutputStream( new BufferedOutputStream(new FileOutputStream("prueba.dat",true))); dos.writeDouble(d1); dos.close(); } catch(java.io.IOException ioex){ } }
Metodo para escribir en un archivo de binario
public void mostrar(){ // PERMITE MOSTRAR EL VALOR REAL EN EL ARCHIVO String s; try { DataInputStream disco= new DataInputStream(new BufferedInputStream(new FileInputStream("prueba.dat"))); File f= new File("prueba.dat"); double d2; while(f.exists( ) ){ d2=disco.readDouble( ); System.out.println(d2); } disco.close( ); } catch(java.io.FileNotFoundException fnfex){ } catch(java.io.IOException ioex){ } } public static void main(String arg[ ]){ BINARIO fun= new BINARIO( ); fun.escritura(Float.parseFloat(fun.dato("Ingrese un real > "))); fun.escritura(Float.parseFloat(fun.dato("Ingrese un real > "))); fun.mostrar(); }}
Usando archivos binarios
Metodo para visualizar la informacion de un archivo de binario
RANDOMACCESSFILE
RandomAccessFile se usa para los archivos que contengan registros de tamaño conocido, de forma que se puede mover de un registro a otro utilizando seek(), para despues leer o modificar los registros.
RandomAccessFile tiene un comportamiento esencialmente distinto al de otros tipos de E/S, puesto que se puede avanzar y retroceder dentro de un archivo.
Fundamentalmente un RandomAccessFile funciona igual que un DataInputStream unido a un DataOutputStream junto con los metodos getFilePointer para averiguar la posición actual en el archivo, seek() para moverse a un nuevo punto del archivo, y length() para determinar el tamaño máximo del mismo.
import java.lang.*;import java.io.*;class ARCH { BufferedReader teclado = new BufferedReader(new InputStreamReader(System.in)); String n; int clave=0; int edad=0; long tregistro=58; long cregistros=0;
public String leer(String m){ System.out.print(m+" : "); try{ n=teclado.readLine( ); } catch(Exception e){ } return n; }
RANDOMACCESSFILE
Método para lectura de datos
Continua la clase ARCH…
RANDOMACCESSFILE void INGRESAR( ){ String nombre=""; try { File arch=new File("archivo1.dat"); RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); clave = Integer.parseInt(leer("dame clave")); nombre=leer("dame nombre"); if (nombre.length( ) < 25){ for(int i=nombre.length( ); i <25; i++) nombre=nombre+" "; } else{ nombre=nombre.substring(0,25); }; edad = Integer.parseInt(leer("dame edad")); if (archivo.length( )!= 0){ archivo.seek( archivo.length( ) ); }; archivo.writeInt(clave); archivo.writeChars(nombre); archivo.writeInt(edad); archivo.close( ); } catch(FileNotFoundException f) { System.out.println("Arch. No existe"); } catch (IOException e) { System.out.println("Error al escribir"); } }
Se registran nombres con a lo mas 25 caracters
…Continua la clase ARCH…
void ELIMINAR( ){ int c1; String n1=""; int e1; String nombre=""; boolean cond=false; int k; try{
File arch=new File("archivo1.dat"); RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); cregistros=archivo.length( ) / tregistro; int n=0; int c = Integer.parseInt(leer("dame clave a buscar")); while(n<cregistros){
archivo.seek(n*58); clave=archivo.readInt( ); if(clave == c){ cond=true; break;} n=n+1;
} k=n;
RANDOMACCESSFILE
…Continua la clase ARCH…
El método ELIMINAR es muy largo, en esta parte se busca la clave a eliminar,…cuando se da con ella se captura la posición en el archivo y luego se asigna a k(k = n)
if(cond){ for(;;){ k++; if(k< cregistros){ archivo.seek(k*58); c1=archivo.readInt( ); for(int i = 0; i < 25; ++i){ n1 += archivo.readChar( );}; e1=archivo.readInt( ); archivo.seek(n*58); archivo.writeInt(c1); archivo.writeChars(n1); archivo.writeInt(e1); n1=""; n++; } else { archivo.close( ); File arch2=new File("archivo1.dat"); RandomAccessFile archivo2=new RandomAccessFile(arch,"rw"); archivo2.setLength(n*58); archivo2.close(); break; } } } else archivo.close( );}catch(FileNotFoundException f) { System.out.println("Arch. no existe"); }catch (IOException e) { System.out.println("Error al escribir"); } }
Se comprime el archivo
RANDOMACCESSFILE
…Continua la clase ARCH…
void MOSTRAR( ){ int clave=0; String nombre=""; int edad=0; try { File arch=new File("archivo1.dat"); RandomAccessFile archivo=new RandomAccessFile(arch,"rw"); cregistros=archivo.length( ) / tregistro; for (int r=0; r < cregistros; r++){ clave=archivo.readInt( ); for(int i = 0; i < 25; ++i){ nombre += archivo.readChar( ); }; edad=archivo.readInt( ); System.out.println(clave+" "+nombre+" "+edad); nombre=""; }; archivo.close( );}catch(FileNotFoundException f) { System.out.println("Arch. no existe"); }catch (IOException e) { System.out.println("Error al escribir"); }
}
RANDOMACCESSFILE
…Continua la clase ARCH…
public static void main(String[ ] args) { ARCH a=new ARCH();for(;;){ System.out.println("REGISTRAR <1>\n VER <2>\n ELIMINAR <3>\n SALIR <4>"); switch (Integer.parseInt(a.leer("opcion : "))){ case 1:a.INGRESAR( );break; case 2:a.MOSTRAR( );break; case 3:a.ELIMINAR( );break; case 4:System.exit(0); } } } // cierra main
RANDOMACCESSFILE
REGISTRAR <1> VER <2> ELIMINAR <3> SALIR <4>
opción : : 2
345 CARLOS 45789 MARIA 12
Que es Serialización?Que es Serialización?
La serialización es el proceso de convertir el estado de un objeto a un formato que se pueda almacenar o transportar.
Durante este proceso, los campos público y privado del objeto y el nombre de la clase, incluido el ensamblado que contiene la clase, se convierten en una secuencia de bytes que, a continuación, se escribe en una secuencia de datos.
Cuando, después, el objeto se deserializa, se crea una copia exacta del objeto original.
La serie de bytes o el formato pueden ser usados para crear un nuevo objeto que es idéntico en todo al original, incluido su estado interno (por tanto, el nuevo objeto es un clon del original).
Serialización para Serialización para crear un objetocrear un objeto
La serialización es un mecanismo ampliamente usado para transportar objetos a través de una red, para hacer persistente un objeto en un archivo o base de datos, o para distribuir objetos idénticos a varias aplicaciones o localizaciones.
Serialización para Serialización para transporte de objetostransporte de objetos
Soporte de LenguajesSoporte de Lenguajes
Varios lenguajes de programación orientados a objeto soportan la serialización de forma directa.
Algunos de ellos son:
Objective-C Java Delphi C# Visual Basic .NET Perl Python
USANDO SERIALIZACIONUSANDO SERIALIZACION La serialización en Java está presente desde la
versión 1.1 y está incluida en el paquete java.io.
Éste contiene la interfaz Serializable, que será implementada por la clase que necesita el uso de esta característica. Así mismo, se añaden dos métodos a dicha clase, que son:
private void writeObject(java.io.ObjectOutputStream out) throws IOException
private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException;
El primero se encargará de almacenar el estado del objeto en un flujo de datos y el segundo, como es de esperar, de recuperarlo.
Para serializar un objeto:
Crear un objeto OutputStream. Envolverlo dentro un objeto ObjectOutputStream. Llamar al método writeObject().
SERIALIZAR UN OBJETOSERIALIZAR UN OBJETO
DESERIALIZAR UN OBJETODESERIALIZAR UN OBJETO
Para deserializar:
Crear un InputStream.Envolverlo dentro de un ObjectInputStream.Llamar al método readObject().Se efectúa un upcast a Object, por lo que hay que realizar un downcasting.
import java.io.*;public class serial { public static void main(String args[ ]) {
//Serializamos el objeto try { MiClase obj1 = new MiClase("String", 15); System.out.println("Objeto 1: " + obj1); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serial")); oos.writeObject(obj1); oos.close( ); } catch (Exception e) {System.out.println("si"+e.getMessage());System.exit(0);} //Deserialización del objeto try { MiClase obj2; ObjectInputStream ois = new ObjectInputStream(new FileInputStream("serial")); obj2 = (MiClase)ois.readObject( ); ois.close(); System.out.println("Objeto 2: " + obj2); } catch(Exception e) {System.out.println(e.getMessage( ));System.exit(0);} }}
USANDO SERIALIZACIONUSANDO SERIALIZACION
serializando
deserializando
class MiClase implements Serializable { String s; int i; public MiClase(String s, int i) { this.s = s; this.i = i; } public String toString() { return "s=" + s + "; i=" + i; }}
USANDO SERIALIZACIONUSANDO SERIALIZACION
Clase serializable
Un problema en el ObjectOutputStream es que al instanciarlo, escribe unos bytes de cabecera en el fichero, antes incluso de que escribamos nada. Como el ObjectInputStream lee correctamente estos bytes de cabecera, aparentemente no pasa nada y ni siquiera nos enteramos que existen.
El problema se presenta si escribimos unos datos en el fichero y lo cerramos. Luego volvemos a abrirlo para añadir datos, creando un nuevo ObjectOutputStream así
Esto escribe una nueva cabecera justo al final del fichero. Luego se irán añadiendo los objetos que vayamos escribiendo. El fichero contendrá lo del dibujo, con dos cabeceras.
PROBLEMA EN LA PROBLEMA EN LA SERIALIZACIONSERIALIZACION
PRIMERA SESION SEGUNDA SESION
cabecera obj1 obj2 obj3 cabecera obj4 obj5 obj6 obj7
PROBLEMA EN LA PROBLEMA EN LA SERIALIZACIONSERIALIZACION
PRIMERA SESION SEGUNDA SESION
cabecera obj1 obj2 obj3 cabecera obj4 obj5 obj6 obj7
¿Qué pasa cuando leamos el fichero?. Al crear el ObjectInputStream, este lee la cabecera del principio y luego se pone a leer objetos. Cuando llegamos a la segunda cabecera que se añadió al abrir por segunda vez el fichero para añadirle datos, obtendremos un error StreamCorruptedException y no podremos leer más objetos.
Una solución es evidente, no usar más que un solo ObjectOuptutStream para escribir todo el fichero. Sin embargo, esto no es siempre posible.
protected void writeStreamHeader() throws IOException{// No hacer nada.}
PROBLEMA EN LA PROBLEMA EN LA SERIALIZACIONSERIALIZACION
PRIMERA SESION SEGUNDA SESION
cabecera obj1 obj2 obj3 cabecera obj4 obj5 obj6 obj7
Una solución es hacer nuestro propio ObjectOutputStream, heredando del original y redefiniendo el método writeStreamHeader() como en la figura, vacío, para que no haga nada.
SERIALIZACION CON UN OBJETO SERIALIZACION CON UN OBJETO COMPUESTOCOMPUESTO
class ASIGNATURA implements Serializable{private String nomb;private String cred;void REG(String n, String c ){ nomb=n; cred= c;}void VIS(){System.out.println("ASIG: "+nomb+" CRED: "+cred);}
}
class ALUMNO implements Serializable { private int cod; private String n; ASIGNATURA a=new ASIGNATURA(); public ALUMNO(String n, int c) { String asig="",cre=""; this.cod = c; this.n = n; asig=PRINCIPAL.leer("leer asignatura: "); cre=PRINCIPAL.leer("leer credito: "); a.REG(asig, cre); } void VIS(){ System.out.println("COD: "+cod+" NOMB: "+n); a.VIS(); }}
Objetos de ambas clases se serializaran
class MiObjectOutputStream extends ObjectOutputStream{ /** Constructor que recibe OutputStream */ public MiObjectOutputStream(OutputStream out) throws IOException { super(out); }
/** Constructor sin parámetros */ protected MiObjectOutputStream() throws IOException, SecurityException { super(); }
/** Redefinición del método de escribir la cabecera para que no haga nada. */ protected void writeStreamHeader() throws IOException { }
}
SERIALIZACION CON UN OBJETO SERIALIZACION CON UN OBJETO COMPUESTOCOMPUESTO
Redefinición de la clase ObjectOutputStream para que no escriba una cabecera al principio del Stream
class PRINCIPAL{ public void escribeFichero(String fichero, String x,int y){ try { ALUMNO obj1 = new ALUMNO(x,y); obj1.VIS(); ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(fichero)); oos.writeObject(obj1); oos.close( ); } catch (Exception e){ {System.out.println(e.getMessage());} } } public void anhadeFichero (String fichero,String x,int y){ try{ ALUMNO obj1 = new ALUMNO(x,y); obj1.VIS(); MiObjectOutputStream oos = new MiObjectOutputStream(new FileOutputStream(fichero,true)); oos.writeObject(obj1); oos.close( ); } catch (Exception e){ {System.out.println(e.getMessage());} } }
SERIALIZACION CON UN OBJETO SERIALIZACION CON UN OBJETO COMPUESTOCOMPUESTO
Continua la clase PRINCIPAL …
public void leeFichero(String fichero){ try { ObjectInputStream ois = new ObjectInputStream(new FileInputStream(fichero)); ALUMNO aux = (ALUMNO)ois.readObject( ); while (aux!=null) { aux.VIS(); aux = (ALUMNO)ois.readObject(); } ois.close(); } catch (EOFException e1) { System.out.println ("Fin de fichero"); } catch (Exception e2) { e2.printStackTrace(); } } static String leer(String m){ BufferedReader b= new BufferedReader(new InputStreamReader(System.in)); String c=""; System.out.println(m); try{ c=b.readLine();} catch(Exception e){ } return c; }
SERIALIZACION CON UN OBJETO SERIALIZACION CON UN OBJETO COMPUESTOCOMPUESTO
…..Continua de la clase PRINCIPAL
Continua la clase PRINCIPAL…
void Menu(){ int op=0,cod; String nom=""; Scanner s=new Scanner(System.in); for(;;){ System.out.println("\n Registrar <1>\n Añadir <2>\n Visualizar <3>\n Salir <4>"); op=s.nextInt(); switch(op){ case 1: nom=leer("leer nombre: "); cod= Integer.parseInt(leer("leer codigo: ")); escribeFichero("academico",nom, cod); break; case 2: nom=leer("leer nombre: "); cod= Integer.parseInt(leer("leer codigo: ")); anhadeFichero("academico",nom, cod); break; case 3: leeFichero("academico"); break; case 4: System.exit(0); }//fin del switch }// fin del for } static public void main(String arg[]){ PRINCIPAL p=new PRINCIPAL(); p.Menu(); } } // FIN DE LA CLASE PRINCIPAL
CON UN OBJETO COMPUESTOCON UN OBJETO COMPUESTO
PERSISTENCIA HOYPERSISTENCIA HOY
JAVA: posee un sistema de serialización de objetos a disco, más o menos automático.
C++: no posee ningún sistema de serialización, utilizándose mecanismos que tienen como base la grabación directa de objetos a disco:
fwrite(&objeto, sizeof(objeto), 1,Fichero)
Salvar los objetos depende del lenguaje en el que se esté trabajando:
PERSISTENCIA HOYPERSISTENCIA HOY
En los lenguajes como C++, sólo puede recuperarse el estado de un objeto guardado previamente; sin embargo no puede saberse a qué clase pertenece el objeto, y ni siquiera si es un objeto.
En lenguajes como Java, la recuperación es un poco mejor, puesto que podemos obtener el archivo .class y el de datos; sin embargo, la recuperación y el tratamiento de estos archivos sólo es realmente sencillo si es la misma aplicación que los grabó la que los va a utilizar.
ESENCIA DE LA PERSISTENCIAESENCIA DE LA PERSISTENCIA
La investigación en persistencia trata de ir un paso más allá que la idea inicial de guardar objetos en archivos de la misma forma que es posible guardar todo tipo de datos en ellos.
Se trata de proporcionar un mecanismo tan automático como sea posible para la recuperación y salvaguarda de objetos, resultando por tanto obsoletos los conceptos de:
Archivo: ya no es necesario. Distinción entre memoria primaria y
secundaria: ya no es necesaria.