You are on page 1of 8

Paltario Programaci´n 2009-1 o Ficheros en C

Osvaldo Mena Requena 2773008-6 omena@alumnos.inf.utfsm.cl Pablo Jacobi Inostroza 2773022-1 pjacobi@alumnos.inf.utfsm.cl

10 de junio de 2009
El presente texto se ha desarrollado con la finalidad de ayudar al entendimiento del uso de ficheros (archivos) en el lenguaje de programaci´n C. Adem´s pretendemos ayudar a los mechones en la ultima oportunidad de pasar o a ´ el ramo. hh((( ( Cualquier consulta, sugerencia, aporte ((reclamo. Rogamos que se comunique con cualquiera de los autores y/o hhh h mencionados en la cabecera de esta p´gina. a

1.

Ficheros en C

En el principio de los tiempos, cuando se programaba con tarjetas de cart´n perforadas y en c´digo binario o o como los machos, exist´ la gran problem´tica de almacenar los datos que los programas obten´ en su ejecuci´n, ıa a ıan o haci´ndolos m´s in´tiles y menos pr´cticos (Como los programas que calculan n´meros primos). e a u a u Es por la necesidad de almacenamiento que nacieron los archivos, con los cuales podemos conservar nuestros datos a largo plazo de una manera bastante pr´ctica y bonita (Ni tanto, pero bueno). a

1.1.

Tipos de Ficheros en C

B´sicamente existen dos tipos de archivos: a 1. Archivos de Texto. 2. Archivos Binarios. Lo m´s com´n para el Padawan programador es trabajar con Archivos de Texto (Como cuando trabajamos en a u el Bloc de Notas de windows), a estos archivos se les denomina Archivos de Texto, o de forma m´s t´cnica, Ficheros a e de Texto Plano. Sin embargo, estos archivos son poco eficientes al momento de trabajar con tipos de datos m´s complejos. a ¿Razones? He aqu´ unas cuantas: ı 1. Es ambigua la forma en que estos se leen. 2. Al momento de leer cadenas de car´cteres con muchos datos en ella hay que hacer un gran esfuerzo (tanto a mental como a nivel de c´digo) para entender que es lo que ellas tienen (Por ejemplo, Juan Perez puede ser o un campo de nombre, o pueden ser dos campos... nombre y apellido). 3. En general, el tratar con este tipo de archivos es bastante tedioso. Con el tiempo, el aprendiz de programador se dar´ cuenta que los archivos binarios ofrecen mayor flexibilidad y limpieza al trabajar. a

‘‘MODO DE APERTURA’’). a 2.‘‘MODO DE APERTURA’’). pero para fines practicos. 2.2. para esto se utiliza la funci´n fopen: o variable = fopen(‘‘nombre_de_archivo. Luego. a continuaci´n se presenta una tabla resumen1 .txt’’.txt’’. esto significa.1. por ejemplo: a FILE *variable=fopen(‘‘nombre_de_archivo. por convenci´n.). Jugando con archivos Punteros a Archivos Quiz´s el t´rmino puntero le suene a chino al novato. a o Figura 1: Modos de Apertura de Archivos Se puede apreciar que los modos para archivos de texto y binarios son similares. llevan una “b” (de binario). leer o modificar. El modo de apertura depende de lo que se quiera hacer. necesitamos abrir el archivo. Abriendo un Archivo Para abrir un archivo necesitamos declarar una variable del tipo FILE *variable. cabe destacar que es posible declarar el puntero y abrir el archivo al mismo tiempo. u u o se ocupan las min´sculas. la diferencia es que los modos binarios. nos permitir´ acceder al archivo en su totalidad. 1 Gracias Patty =D 2 . la cual utilizaremos despues para accesar al archivo que queramos. El modo de operar con los archivos (Sean del tipo que sean) es mediante punteros. u Adem´s. sin embargo. en el texto presente se tratar´ coa e a mo una variable que tiene un * antes del nombre (Ejemplo: FILE *puntero. ya sea para escribir.2. NOTA: Los modos de apertura pueden ser escritos en min´scula o en may´scula. que nuestra variable FILE *puntero. que o contiene los modos de apertura m´s usados para la operaci´n de archivos.

si no. declarelo de la forma FILE *variable.‘‘r’’)) == NULL){ printf(‘‘El archivo no existe. no file ni File ni fIle ni FiLe. Este contiene nombres de alumnos y el promedio respectivo en el ramo de Programaci´n: o Figura 2: test.rb). ni ninguna de las otras 10 combinaciones.. //Se finaliza la ejecucion del programa al fallar la apertura } 2.txt’’. El asterisco solamente se ocupa en la declaraci´n. 2. FILE variable. variable = fopen(archivo. 2. 2. Errores comunes al declarar el puntero a archivo 1.2.txt’’. no es m´gico.4. no sea tonto. A continuaci´n se muestra un c´digo de a o o comprobaci´n est´ndar. Comprobando la apertura Una buena pr´ctica de programaci´n es corroborar la apertura exitosa del archivo. es FILE! . T´cnicamente se puede trabajar con una variable sin el asterisco. se estar´ llamando a variables y no a cadenas. bien! Pero ahora. a a a 2. fopen(‘‘archivo. pero aumenta la come plejidad del programa y requiere una muy buena base en punteros.. archivo. y arrojar´ un lindo error. tales como leer y e escribir. FILE *variable=archivo...1. Errores comunes al abrir el archivo 1..2. *variable = fopen(‘‘archivo. Se abre el archivo. ahora necesitamos hacer operaciones sobre ´l.2.2. ¿C´mo accedo a ´l? Es estrictao e mente necesario asignarlo a un puntero a archivo previamente creado.txt y rb son cadenas de texto esto significa que tienen que ir entre comillas. o a if((variable = fopen(‘‘archivo. file *variable. Si bien. C se marear´. que quieres que lea?\n’’). return 0.. Consideraremos el siguiente archivo de texto de prueba. a 3.txt. Trabajando con archivos de Texto (plano) Ya tenemos listo nuestro acceso al archivo. en el caso de que un archivo a o no se pueda abrir exitosamente fopen asignar´ NULL a la variable puntero.‘‘rb’’).. o 3.3. (Con asterisco!).txt 2 3 .‘‘rb’’).txt. para mostrar las distintas operaciones. el lenguaje C es poderoso.txt’’.

es decir. sin embargo.‘‘%s %d’’. ya que si leemos la l´ o ınea completa. y blah blah blah.‘‘Formato de lectura’’.var1.txt’’. variable = fopen(‘‘test. //Como accedemos a las variables? Esta todo en una sola cadena! //Muy complicado. estas har´n lo contrario. mejor fscanf para este caso.puntero_archivo).. !feof solo retornara 0 si es que hemos llegado al final del archivo. pero las m´s ocupadas son fscanf y fgets.100. while(!feof(variable)) fgets(cadena..3 fgets(cadena. La funci´n feof retorna un 1 (verdadero) si es que hemos llegado al final del archivo. mas suerte para la otra =( 2.4. 4 . Gracias a esto. Gracias al ‘‘!’’. se debe anteponer & a menos que se trate de una cadena (string).variable). Lectura Existen muchas funciones de lectura de archivos de texto. 2.varn). ambos datos estan en la misma l´ ınea.numero de caracteres.1. que se interpreta como falso. char cadena[100]. int nota. obtenemos el resultado contrario. necesitamos una forma de accesar a cada una de ellas hasta llegar al final del archivo..4. por lo tanto. luego debemos separar la cadena.‘‘r’’).‘‘r’’).txt’’..4. lee un formato de cadena especificado por el programador (Como cuando se leen datos con scanf) y fgets lee una l´ ınea completa o parte de ella (Seg´n el n´mero de u u car´cteres que hayamos especificado).3. Lectura avanzada A veces necesitamos leer un archivo completo.apellido. con lo cual terminaremos el ciclo.txt’’. la cual nos indicar´ si hemos llegado al final del archivo. u Con fscanf: FILE *variable. fgets(cadena.variable). recurriremos a la funcion feof. convertir el n´mero a entero. !feof retornara 0. a FILE *variable. La diferencia entre ambas funciones es que fscanf. variable = fopen(‘‘test. a Palta: Nos podemos dar cuenta que en el archivo de ejemplo.100. podemos hacer un while que lea l´ ınea por l´ ınea. a La sintaxis es parecida a las funciones anteriores.2. char cadena[100].var3. a fscanf(puntero_archivo. son pocas las veces en que sabemos cuantas l´ ıneas contiene. char apellido[100]. variable = fopen(‘‘test. Con fgets: FILE *variable. 3 Recordar que al almacenar datos en una variable. y cuando se llegue al final del archivo. sin embargo. fscanf(variable.. Cuando nos enfrentemos a una situaci´n de este estilo.var2. tomar´n datos que tenga el programa y los pondr´ en un a a a archivo de texto. mientras que ellas leen de un archivo y llevan los datos al programa. pero las m´s ocupadas son fprintf y fputs. Escritura Existen muchas funciones de lectura de archivos de texto. y un 0 (falso) en caso o contrario.2. Para esto. es decir. se aconseja ocupar fscanf.‘‘r’’).&nota).

es necesario colocar el \n. ya que no se muestra directamente su contenido. }.‘‘a’’).txt’’. Diferencias entre archivos de texto plano y binarios Un archivo de texto plano contiene l´ ıneas de texto. podemos asignar las variables una por una. lo cual es un proceso tedioso y poco agradable. en cambio.5.apellido.4 Con fputs: FILE *variable. variable = fopen(‘‘test. con archivos de texto plano se considera como varios datos. raz´n por la cual necesitar´ o ıamos tener los datos. se ruega al estudiante tener nociones de estructuras. se ruega asistir y poner atenci´n a las ayudantias =D).nota). lo cual sirve para pedir los datos o por pantalla. Ahora veremos como estas peque˜as diferencias nos simplifican la vida.var3.1. //Esta vez no necesitamos saber cuantos caracteres guardar Para este ejemplo.puntero_archivo). un archivo e o binario es una buena opci´n.var2.mp3 es un archivo binario). fputs(datos.fprintf(puntero_archivo. char apellido[100]=‘‘Sepulveda’’. fprintf(variable. ya que se asumir´n o a conocimientos b´sicos al respecto (en caso contrario. no como texto propiamente tal. el trabajar con archivos de texto plano se vuelve tedioso y desagradable a la hora ( de tener varios tipos de datos en ´l.variable). int nota. o calcularlos (especialmente en el caso de los n´meros). en cambio. se sigue conservando la ıa integridad de los datos... variable = fopen(‘‘test. a o Como se dijo en un principio. concateıa narlos (unirlos en un solo string) y grabar en el archivo. lo cual producir´ errores. ya que en caso contrario. int nota=20. char apellido[20].5..txt’’. Trabajando con archivos binarios Antes de comenzar esta secci´n.‘‘a’’). ya que si no escribiria todo en la misma l´ ınea 5 . debido a que los datos son o almacenados directamente como bits. en los binarios. Con fprintf: FILE *variable.varn). lo mejor es usar fprintf. 2. Si es de inter´s del programador ocultar la informaci´n contenida en un archivo a simple vista. lo cual es una fuente menos de error para el programa. N´tese que en el primer caso.var1. En cambio. Consideremos la siguiente estructura: n struct alumno{ char nombre[20]. un archivo binario contiene estructuras completas. Si al menos uno de los datos que queremos almacenar contiene espacios. fputs(cadena. la segunda funci´n requiere que u o todo este en la misma cadena.‘‘Formato de escritura’’.‘‘%s %d\n’’. y luego concatenarlos. 4 En el caso del fprintf. los cuales son superiores e o Filsecker o y ampliamente utilizados (un . habr´ que pedir ambos datos. 2. por esta raz´n ((( Dios cre´ los archivos binarios. char datos[100]=‘‘Sepulveda 20’’.

n fread retorna la cantidad de estructuras que ley´ correctamente. Ejemplos: sizeof(int). lo que permite hacer un programa m´s limpio y ordenado. esta recibe por par´metro un tipo de dato y retorna el n´mero o a u de Bytes que este ocupa. fread(&aux.2.1. En esta funci´n tenemos dos elementos que o o no son familiares para los programadores mechones5 : El primero de ellos es el tama˜o de una estructura (En Bytes).Figura 3: As´ se ve un archivo binario ı 2. Leeremos una de ellas y la almacenaremos en una estructura creada en el programa (Variable del tipo struct alumno).archivo). s´lo contamos con una funci´n de lectura: fread.bin’’. //Retorna 4 sizeof(char). de un tipo de n dato cualquiera) se ocupa la funci´n sizeof. y la guaro o da en una del mismo tipo. //Retorna 44. Lectura En este caso.sizeof(struct alumno). ya que hay dos arreglos de char de tama~o 20 y un int n //20*1 + 20*1 + 4 = 44 El segundo de ellos es el n´mero de estructuras que se van a leer.bin con fread*/ 5 Especialmente para los telem´ticos a 6 . tomaremos como ejemplo un archivo que contiene N estructuras del tipo struct alumno.‘‘rb’’). la cual debe estar previamente creada en el programa.nota contienen los campos de la estructura que se leyo desde test.numero de estructuras. la raz´n de esto es que en un archivo binario n o se guardan solamente 1’s y 0’s uno al lado del otro (No se pueden ver con notepad) y fread no tiene como saber que es lo que esta leyendo. struct alumno aux. archivo_binario = fopen(‘‘test.tama~o_estructura.nombre. //Retorna 1 sizeof(struct alumno).5. a Retomando la lectura de un archivo binario. Esta lee una estructura del archivo. Normalmente se lee 1 estructura a la vez. aux.archivo_binario). FILE *archivo_binario. sin embargo. /*Ahora aux. Para poder obtener el tama˜o de una estructura (Y en general. La sintaxis de fread es la siguiente: fread(&nombre_estructura.apellido y aux. para leer m´s de una estructura u a debe estar definido un arreglo de ellas.

Debido a que no conocemos el n´mero exacto de estructuras que este posee.bin. la sintaxis es exactamente la misma de fread.‘‘Hoffmann’’). fwrite(&aux.‘‘rb’’). strcpy(aux. es la misma: fclose(archivo). 2..‘‘ab’’)..bin’’.1.tama~o_estructura. 2. fopen(‘‘test. como se dijo en el inicio del presente texto. aux. es una buena pr´ctica cerrar los archivos despues de n a ocuparlos antes de finalizar la ejecuci´n del mismo. La sintaxis. sin embargo esta puede ser o o cualquiera. para que otros puedan acceder a estos archivos. para archivos binarios tenemos a nuestra disposici´n una sola funci´n para la escritura: o o fwrite. s´lo que fwrite.. esto quiere o u o decir que cuando no encuentre m´s estructuras (Cuando se llegue al fin del archivo) fread retornar´ 0 (No ley´ esa a o tructura alguna).numero de estructuras. 2. debemos leer un archivo binario completo. fwrite(&nombre_estructura. 7 . //Facil. sizeof(struct alumno). //Se leen los datos con fread y luego se compara (Totalmente valido ponerlo dentro del while) while(fread(&aux.5.apellido.5. a 10. incluso los archivos .bin’’. 1. archivo_binario = fopen(‘‘test.nombre. adem´s de que todas ellas deben tener todos sus campos a correctamente asignados. FILE *archivo_binario. Como ya se mencion´ anteriormente fread retorna el n´mero de estructuras que ley´ correctamente. Lectura avanzada Muchas veces. } Con esto podemos leer un archivo binario completa y correctamente. Se grabar´ esa cantidad de estructuras.sizeof(struct alumno).6. el cual contiene N estructuras (Con N muy grande). lo que facilita de sobremanera el trabajo o o a con muchos datos..3. Si bien no afecta en gran medida al desempe˜o del programa.nota = 150. strcpy(aux. y adem´s como no existe feof en u a los archivos binarios se debe recurrir a una estrategia muy interesante. no?. es el cierre de archivos. escribe en un archivo! o struct alumno aux. ya o sea para archivos binarios o de texto plano. a a Por motivos pedag´gicos se ha puesto al archivo de pruebas la extensi´n . el cual ha sido motivo de penalizaci´n en cert´menes del ramo de Programaci´n desde o a o que el lenguaje C ha invadido la USM (Mas o menos desde Mil-novecientos-que-te-importa).‘‘Hubert’’).mp3 son archivos binarios.archivo_binario)... Si se cambia el numero de estructuras a escribir. archivo_binario) == 1){ //Aqui se procesan los datos respectivos . struct alumno aux. FILE *archivo_binario.. a sin embargo.4. n El funcionamiento es similar.archivo). Escritura Similar a la lectura. Cierre de Archivos Un elemento importante.N´tese que la asignaci´n a los campos de las estructuras es autom´tica. debe estar declarado un arreglo de ese largo. por ejemplo.. adem´s se elimina una posible fuente de error (Los archivos binarios son m´s fiables).

2. Resumen (Lectura 5 minutos antes del certamen) Declarar Puntero: FILE *archivo Abrir Archivo: fopen Lectura de Archivos de Texto Plano: fgets y fscanf Escritura de Archivos de Texto Plano: fputs y fprintf Lectura de Archivos Binarios: fread Escritura de Archivos Binarios: fwrite Cerrar Archivo: fclose 8 .7.