Anda di halaman 1dari 65

Archivos en C

M.C. Meliza Contreras Gonzlez

Introduccin

Una computadora puede almacenar grandes cantidades de informacin. Puede acceder a ella de manera muy rpida. Para hacer cualquier cosa es necesario tener MEMORIA disponible, para almacenar variables, recordar valores, etc.

Esta memoria puede ser voltil o persistente.

Introduccin

Memoria primaria (voltil)


CPU A+B=C A

Memoria secundaria (persistente)

B
C

Datos.txt

Memoria RAM

RAM: Random Access Memory. Acceso aleatorio. Voltil, por tanto insegura. Capacidades de cientos de MB. Velocidad de acceso:

Del orden de los nanosegundos (10-9 seg.)

133 MHz 8 ns

Implica que puede transmitir mas de 1 GB/seg.

Memoria RAM

Es necesario

Evitar la volatilidad de la memoria RAM. Aumentar su capacidad a costos razonables. Realizar respaldos de informacin.

HDD

HDD: Hard Drive Disk Acceso aleatorio. Persistente y confiable. Capacidades de decenas de GB. Velocidad de acceso

Del orden de los milisegundos (10-3 seg)

5 10 ms

Transmiten en tasas de decenas de MB/seg.

Archivos

Los archivos son entidades que define el sistema operativo para identificar un conjunto de datos Un archivo tiene un conjunto de atributos

Nombre y extensin. Ubicacin (muchas veces es solo parte del nombre). Tamao. Tipo. Permisos: Lectura , escritura y ejecucin (puede estar especificado por usuarios y grupos) Fecha de creacin y modificacin.

Archivos

Debido a su facilidad de uso y compresin, muchos sistemas utilizan archivos especiales para manejar dispositivos

Teclado Entrada secuencial Pantalla Salida secuencial Impresora Salida secuencial Red, Serial, paralela E/S secuencial Etc...

Todo se resume a saber manejar archivos Si manejan archivos, manejarn al mundo.

Archivos

Se pueden realizar un conjunto de operaciones a travs del sistema operativo con los archivos:

Abrir Cerrar Leer Escribir Mover a una posicin (solo acceso aleatorio)

Archivos

Para abstraer la interaccin entre los archivos y los programas que realicen operaciones sobre ellos, se define el concepto de flujo. Un flujo es como una manguera por donde fluyen datos en uno o ambos sentidos.

Flujos
chao hola

chao

hola

Flujos
VAR

Abrir
Leer Escribir Cerrar hola

Abrir un flujo

Antes de poder utilizar un flujo, debemos abrirlo. Al momento de abrirlo se especifica el modo

Solo lectura (r) Solo escritura (w) Lectura/escritura (rw) Se asigna un descriptor del archivo a nuestro programa Se modifica el estado del archivo

Al abrir:

Abrir un flujo

Estado de un archivo

Si esta abierto para lectura, otros programas pueden tambin abrirlo para lectura, pero no para escritura. Si est abierto para escritura, nadie ms puede abrirlo.

Cerrar un flujo

Al terminar de usarlos, los flujos deben ser cerrados. Al cerrar los flujos, nuevamente se modifica el estado del archivo (para que otros puedan abrirlo). Al salir del programa de manera normal, los flujos se cierran en forma automtica. Si el programa termina de manera anormal, los flujos pueden quedar abiertos.

Leer desde un flujo


Los archivos contienen informacin binaria. Esta informacin puede representar cualquier cosa. Los archivos se separan en dos grandes grupos

Archivos de texto Archivos binarios

Al momento de leer, hay que tener claro el tipo de archivo desde el cual se desea leer informacin.

Leer desde un flujo de texto

Se pueden leer letras, palabras o frases completas. Por lo general se leen de manera secuencial, desde la primera letra hasta el fin de archivo.

Leer desde un flujo binario

Pueden contener cualquier cosa. Por lo general se leen de manera aleatoria. Pueden contener estructuras de datos.

Escribir en un flujo

Tambin depende del tipo de archivo.

Por lo general, el escribir en un flujo no significa que la informacin se guarde de manera inmediata en el archivo.
La operacin de escritura secundaria es muy costosa. en memoria

Para mejorar el rendimiento se utiliza un buffer.

Escribir en un flujo
2 datos [Llenando buffer]

5 datos

[Llenando buffer]

1 datos [buffer lleno]

[Vaciando buffer]

Mover a una posicin

Accin permitida solo para archivos de acceso directo. Al abrir un archivo, se define una posicin al comienzo de este.

Al leer o escribir de manera secuencial, esta posicin se actualiza automticamente a la posicin siguiente.
Se puede modificar de manera manual esta posicin para leer o modificar un datos especifico o en un orden distinto al secuencial.

E/S para archivos

Las funciones y tipos estn definidos en <stdio.h>

FILE

Estructura que define un descriptor de archivo

EOF

Constante para detectar el fin del archivo

Apertura de flujos

fopen

Abre un archivo para su uso


FILE* fopen(char* nombre, char* modo);

Devuelve el descriptor del archivo para su uso posterior. NULL en caso de error Nombre del archivo a abrir

Modo de apertura (lectura, escritura, etc.)

Apertura de flujos
r
w a rb

Abrir para lectura


Abrir para escritura Abrir para aadir datos al final Abrir para lectura binaria

wb
ab r+ w+

Abrir para escritura binaria


Abrir para aadir datos binarios Abrir para lectura/escritura Crear archivo para lectura/escritura

a+
r+b w+b a+b

Abre o crea para aadir datos


Abre para lectura/escritura binaria Crea para lectura/escritura binaria Abre o crea para aadir datos binarios

Cierre de flujos

fclose

Cierra un archivo previamente abierto, liberando los recursos asociados al programa. int fclose(FILE* f);

xito de la operacin (0 en caso de xito)

Flujo a cerrar

Apertura y cierre
#include <stdio.h> int main(){ FILE* archivo; archivo = fopen("testt.txt","r"); if(archivo!=NULL){ if(fclose(archivo)!=EOF) printf("Ok!\n"); else printf("Error al cerrar!\n"); }else printf("Error al abrir!\n");

Manejo de errores

En C, muchas funciones modifican una variable global cuando ocurre un error. Esta variable puede ser consultada para saber ms acerca del error. La variable global se llama errno.

Se define en <errno.h>

La funcin strerror(int e) entrega una descripcion de un cdigo de error.

Se define en <string.h>

Manejo de errores
#include <stdio.h> int main(){ FILE* archivo; archivo = fopen("testt.txt","r"); if(archivo!=NULL){ if(fclose(archivo)!=EOF) printf("Ok!\n"); else printf("Error al cerrar!\n"); }else printf("Error al abrir: %s\n",strerror(errno));

Lectura de carcteres

fgetc

Lee un carcter desde un archivo abierto para lectura. int fgetc(FILE* f);

Devuelve el carcter ledo como un entero. En caso de error, devuelve EOF

Descriptor de archivo

Lectura de carcteres

fgets

Lee desde un archivo abierto para lectura hasta un largo fijo o el fin de lnea.
fgets(char* cadena, int longitud, FILE* f);

Arreglo de caracteres donde guardar la cadena leda

Cantidad mxima de carcteres a leer

Descriptor de archivo

Lectura de carcteres
int main(){ FILE* archivo; archivo = fopen("test.txt","r"); if(archivo!=NULL){ char c; do{ c = fgetc(archivo); printf("%c",c); }while(c!=EOF); fclose(archivo); } }

Lectura de carcteres
int main(){ FILE* archivo; archivo = fopen("test.txt","r"); if(archivo!=NULL){ char* res; char cadena[128]; do{ res=fgets(cadena,128,archivo); if(res!=NULL) printf("%s",cadena); }while(res!=NULL); fclose(archivo);
} }

Lectura de carcteres

Una funcin muy til es feof, quien detecta si se ha alcanzado o no el fin de archivo. feof

Devuelve verdadero si se ha alcanzado el fin de archivo int feof(FILE* f);

1: Fin de archivo 0: otro caso

Descriptor de archivo

Lectura de carcteres
int main(){ FILE* archivo; archivo = fopen("test.txt","r"); if(archivo!=NULL){ char cadena[128]; while(!feof(archivo)){ fgets(cadena,128,archivo); printf("%s",cadena); } fclose(archivo); } }

Lectura de carcteres

Existe una version de scanf para archivos


int fscanf(FILE* f, char* fmt, ...);

Numero de conversiones realizadas con xito

Descriptor de archivo

Variables a Modificar (referencias!)

Lectura de carcteres
int main(){ FILE* archivo; archivo = fopen("test.txt","r"); if(archivo!=NULL){ char c; while( fscanf(archivo,"%c",&c)==1 ) printf("%c",c); fclose(archivo); } }

Escritura de carcteres

Cada funcin de lectura tiene su pareja


int fputc(int c , FILE* f);

EOF en caso de error EOF en caso de error Devuelve el numero de transformaciones realizadas con xito.

int fputs(char* cadena, FILE* f);

int fprintf(FILE* f, char* fmt, ...);

Escritura de carcteres
archivo2 = fopen("test2.txt","w+"); ... do{ c = fgetc(archivo); if(c!=EOF){ fputc(c,archivo2); printf("%c",c); } }while(c!=EOF);

Escritura de carcteres
do{ res=fgets(cadena,128,archivo); if(res!=NULL){ printf("%s",cadena); fputs(cadena,archivo2);} }while(res!=NULL);

Escritura de carcteres
while( fscanf(archivo,"%c",&c)==1 ){ printf("%c",c); fprintf(archivo2,"%c",c); }

Escritura de carcteres

fflush

Vacia el buffer de escritura int fflush(FILE* f);

Devuelve EOF en caso de error

Descriptor de archivo

Otros archivos

Archivos de nmeros

Para leer datos desde un archivo de texto como enteros (o nmeros en general) se puede utilizar fscanf. Para escribir datos numricos en archivos de texto se puede utilizar fprintf. Los archivos deben ser abiertos en modo texto. Se utilizan las conversiones %d y %f ya vistas.

Archivos de nmeros

Ejemplo: Archivo de texto con nmeros en un formato fijo

1 2 3 4 7, 8, 9, 10 1.4 ; 0.7 ; 9.001 ; 67.0

Archivos de nmeros
#include <stdio.h> int main(){ FILE* archivo; archivo = fopen("test3.txt","r"); if(archivo!=NULL){ int ds[4],i; double fs[4]; fscanf(archivo,"%d %d %d %d\n", &ds[0],&ds[1],&ds[2],&ds[3]); fscanf(archivo,"%d, %d, %d, %d\n", &ds[0],&ds[1],&ds[2],&ds[3]); fscanf(archivo,"%lf ; %lf ; %lf ; %lf\n" &fs[0],&fs[1],&fs[2],&fs[3]); fclose(archivo); } }

Archivos mixtos

Archivos de texto con datos alfanumricos Basta con especificar el tipo de conversin deseada para cada tipo de dato.

colo-colo 0 huachipato 3 everton 5 cobreloa 1 u.Catolica 2 wanderers 3

Archivos mixtos
#include <stdio.h> int main(){ FILE* archivo; archivo = fopen("test4.txt","r"); if(archivo!=NULL){ char visita[32], local[32]; int gvisita, glocal; int r=4; while(1){ r=fscanf(archivo,"%s %d %s %d\n", local,&glocal,visita,&gvisita); if(r!=4) break; if(glocal>gvisita) printf("Gana local (%s)\n",local); else if(glocal<gvisita) printf("Gana visita (%s)\n",visita); else printf("Empate\n"); } fclose(archivo); } return 1; }

Archivos binarios

Deben ser abiertos en modo binario. La informacin se guarda en formato binario. Si se abre el archivo con un editor de texto, aparece basura. Se pueden intercalar distintos tipos de datos

Archivos binarios
fread

Lee datos binarios desde un archivo


size_t fread(
Variable donde dejar la informacin leda Tamao del tipo de dato Numero de elementos A leer

void* buffer, size_t num_bytes, unsigned int, size_t cuenta, Nmero de bytes ledos FILE* fp);
Flujo desde donde leer

Archivos binarios

fwrite

Escribe datos binarios a un archivo

size_t fwrite(
void* buffer, size_t num_bytes, size_t cuenta, FILE* fp);

Variable desde donde tomar la informacin

Tamao del tipo de dato Numero de elementos A escribir

unsigned int, Nmero de bytes escritos

Flujo donde se debe escribir

Archivos binarios

sizeof

Entrega el numero de bytes que ocupa un tipo de dato Es un operador calculado en tiempo de compilacin. sizeof(int) 4 int i; sizeof(i) 4

Archivos binarios
void escribir(FILE* archivo){ archivo = fopen("test5.dat","w+b"); if(archivo!=NULL){ int i,k; k=1; for(i=0;i<10;i++){ size_t ws; ws = fwrite(&k,sizeof(k),1,archivo); k=k*2; printf("%d enteros escritos en %d bytes\n",ws, ws*sizeof(int)); } fclose(archivo); } }

Archivos binarios
void leer(FILE* archivo){ archivo = fopen("test5.dat","r+b"); if(archivo!=NULL){ int i,k; while(fread(&k,sizeof(int),1,archivo)==1){ printf("%d\n",k); } fclose(archivo); } }

Archivos binarios
int main(int argc, char* argv[]){ FILE* archivo; printf("%s",argv[1]); if(argc>1 && strcmp(argv[1],"w")==0) escribir(archivo); else leer(archivo); return 1;

Archivos binarios

As como se puede leer y escribir datos simples, tambin se pueden leer y escribir datos estructurados. El esquema es el mismo, basta con especificar el tamao correcto.

Archivos binarios
struct pokemon{ char nombre[12]; int tipo; //0: fuego, 1:planta, //2:agua, 3:electrico double fuerza; double energia; };

Archivos binarios
void escribir(FILE* archivo){ archivo = fopen("test6.dat","w+b"); if(archivo!=NULL){ int i,k; struct pokemon pk1, pk2, pk3; strcpy(pk1.nombre,"pikachu"); pk1.tipo=3; pk1.fuerza=120; pk1.energia=87; fwrite(&pk1,sizeof(struct pokemon),1,archivo); fwrite(&pk2,sizeof(struct pokemon),1,archivo); fwrite(&pk3,sizeof(struct pokemon),1,archivo); fclose(archivo); } }

Archivos binarios
void escribir(FILE* archivo){ archivo = fopen("test6.dat","w+b"); if(archivo!=NULL){ int i,k; size_t wb; struct pokemon pk[3]; strcpy(pk[0].nombre,"pikachu"); pk[0].tipo=3; pk[0].fuerza=120; pk[0].energia=87;
wb = fwrite(pk,sizeof(struct pokemon),3,archivo); printf("%d bytes escritos en %d elementos\n", wb*sizeof(struct pokemon), wb); fclose(archivo); }

Archivos binarios
void leer(FILE* archivo){ printf("Leyendo\n"); archivo = fopen("test6.dat","r+b"); if(archivo!=NULL){ int i; struct pokemon pk; while(fread(&pk,sizeof(struct pokemon),1,archivo)==1){ printf("%s\n",pk.nombre); } fclose(archivo); } }

Archivos binarios

En archivos binarios ya no es necesario realizar accesos secuenciales. Es muy natural realizar accesos a estructuras de datos especificas, tanto para lectura como para escritura.

Archivos binarios

fseek

Mueve el cursor de lectura escritura a una posicin especifica del archivo int fseek(FILE* f, long nbytes, int origen);

Cero en caso de xito, distinto de cero en error

Numero de bytes a mover el cursor

Desde donde contar nbytes

Descriptor de archivo

Archivos binarios

fseek

Origen:

SEEK_SET: Principio del archivo SEEK_CUR: Posicin actual SEEK_END: Fin del archivo

Archivos binarios
ftell

Indica la posicin actual en el archivo (bytes respecto al inicio) long int ftell(FILE* f);

Posicin del archivo, -1 en caso de error.

Descriptor de archivo

Archivos binarios
void leern(FILE* archivo, int n){ printf("Leyendo %d\n",n); archivo = fopen("test6.dat","r+b"); if(archivo!=NULL){ int i; struct pokemon pk; fseek(archivo, n*sizeof(struct pokemon),SEEK_SET); fread(&pk,sizeof(struct pokemon),1,archivo); printf("%s\n",pk.nombre); fclose(archivo); } }

Archivos binarios
void leerrev(FILE* archivo){ archivo = fopen("test6.dat","r+b"); if(archivo!=NULL){ int i; struct pokemon pk; fseek(archivo,-1*sizeof(struct pokemon),SEEK_END); while(fread(&pk,sizeof(struct pokemon),1,archivo)==1){ printf("%s\n",pk.nombre); fseek(archivo,-2*sizeof(struct pokemon),SEEK_CUR); } fclose(archivo); } }

Anda mungkin juga menyukai