Curso de CEl Rincón del C - www.elrincondelc.com

Otras funciones para el manejo de ficheros

[Anterior] [Siguiente] [Contenido]

Contenido

Introducción

En este tema vamos a ver otras funciones que permiten el manejo de ficheros.

[Arriba]

fread y fwrite

Las funciones que hemos visto hasta ahora (getc, putc, fgets, fputs) son adecuadas para trabajar con caracteres (1 byte) y cadenas. Pero, ¿qué sucede cuando queremos trabajar con otros tipos de datos?

Supongamos que queremos almacenar variables de tipo int en un fichero. Como las funciones vistas hasta ahora sólo pueden operar con cadenas deberíamos convertir los valores a cadenas (con la función itoa). Para recuperar luego estos valores deberíamos leerlos como cadenas y pasarlos a enteros (atoi).

Existe una solución mucho más fácil. Vamos a utilizar las funciones fread y fwrite. Estas funciones nos permiten tratar con datos de cualquier tipo, incluso con estructuras.

fwrite

Empecemos con fwrite, que nos permite escribir en un fichero. Esta función tiene el siguiente formato:

size_t fwrite(void *buffer, size_t tamano, size_t numero, FILE *pfichero);

Para que quede más claro examinemos el siguiente ejemplo: un programa de agenda que guarda el nombre, apellido y teléfono de cada persona.

#include <stdio.h>

struct {
        char nombre[20];
        char apellido[20];
        char telefono[15];
        } registro;

int main()
    {
    FILE *fichero;

    fichero = fopen( "nombres.txt", "a" );
    do {
       printf( "Nombre: " ); fflush(stdout);
       gets(registro.nombre);
       if (strcmp(registro.nombre,""))
          {
          printf( "Apellido: " ); fflush(stdout);
          gets(registro.apellido);
          printf( "Teléfono: " ); fflush(stdout);
          gets(registro.telefono);
          fwrite( ®istro, sizeof(registro), 1, fichero );
          }
       } while (strcmp(registro.nombre,"")!=0);
    fclose( fichero );
    }
Comprobado con DJGPP

NOTA: El bucle termina cuando el 'nombre' se deja en blanco.

Este programa guarda los datos personales mediante fwrite usando la estructura registro. Abrimos el fichero en modo 'a' (append, añadir), para que los datos que introducimos se añadan al final del fichero.

Una vez abierto abrimos estramos en un bucle do-while mediante el cual introducimos los datos. Los datos se van almacenando en la variable registro (que es una estructura). Una vez tenemos todos los datos de la persona los metemos en el fichero con fwrite:

fwrite( ®istro, sizeof(registro), 1, fichero );

fread

La función fread se utiliza para sacar información de un fichero. Su formato es:

size_t fread(void *buffer, size_t tamano, size_t numero, FILE *pfichero);

Siendo buffer la variable donde se van a escribir los datos leídos del fichero pfichero.

El valor que devuelve la función indica el número de elementos de tamaño 'tamano' que ha conseguido leer. Nosotros podemos pedirle a fread que lea 10 elementos (numero=10), pero si en el fichero sólo hay 6 elementos fread devolverá el número 6.

Siguiendo con el ejemplo anterior ahora vamos a leer los datos que habíamos introducido en "nombres.txt".

#include <stdio.h>

struct {
        char nombre[20];
        char apellido[20];
        char telefono[15];
        } registro;

int main()
    {
    FILE *fichero;

    fichero = fopen( "nombres.txt", "r" );
    while (!feof(fichero)) {
       if (fread( ®istro, sizeof(registro), 1, fichero )) {
              printf( "Nombre: %s\n", registro.nombre );
              printf( "Apellido: %s\n", registro.apellido);
              printf( "Teléfono: %s\n", registro.telefono);
              }
       }
    fclose( fichero );
    }
Comprobado con DJGPP

Abrimos el fichero nombres.txt en modo lectura. Con el bucle while nos aseguramos que recorremos el fichero hasta el final (y que no nos pasamos).

La función fread lee un registro (numero=1) del tamaño de la estructura registro. Si realmente ha conseguido leer un registro la función devolverá un 1, en cuyo caso la condición del 'if' será verdadera y se imprimirá el registro en la pantalla. En caso de que no queden más registros en el fichero, fread devolverá 0 y no se mostrará nada en la pantalla.

[Arriba]

fseek y ftell

fseek

La función fseek nos permite situarnos en la posición que queramos de un fichero abierto. Cuando leemos un fichero hay un 'puntero' que indica en qué lugar del fichero nos encontramos. Cada vez que leemos datos del fichero este puntero se desplaza. Con la función fseek podemos situar este puntero en el lugar que deseemos.

El formato de fseek es el siguiente:

int fseek(FILE *pfichero, long desplazamiento, int modo);

Como siempre pfichero es un puntero de tipo FILE que apunta al fichero con el que queremos trabajar.

desplazamiento son las posiciones (o bytes) que queremos desplazar el puntero. Este desplazamiento puede ser de tres tipos dependiendo del valor de modo:

SEEK_SETEl puntero se desplaza desde el principio del fichero.
SEEK_CUREl puntero se desplaza desde la posición actual del fichero.
SEEK_ENDEl puntero se desplaza desde el final del fichero.

Estas tres constantes están definidas en el fichero <stdio.h>. Como curiosidad se indican a continuación sus definiciones:

#define SEEK_SET	0
#define SEEK_CUR	1
#define SEEK_END	2

Nota: es posible que los valores cambien de un compilador a otro.

Si se produce algún error al intentar posicionar el puntero, la función devuelve un valor distinto de 0. Si todo ha ido bien el valor devuleto es un 0.

En el siguiente ejemplo se muestra el funcionamiento de fseek. Se trata de un programa que lee la letra que hay en la posición que especifica el usuario.

#include <stdio.h>

int main()
    {
    FILE *fichero;
    long posicion;
    int resultado;

    fichero = fopen( "origen.txt", "r" );
    printf( "¿Qué posición quieres leer? " ); fflush(stdout);
    scanf( "%D", &posicion );
    resultado = fseek( fichero, posicion, SEEK_SET );
    if (!resultado)
        printf( "En la posición %D está la letra %c.\n", posicion, getc(fichero) );
    else
        printf( "Problemas posicionando el cursor.\n" );
    fclose( fichero );
    }
Comprobado con DJGPP

ftell

Esta función es complementaria a fseek, devuelve la posición actual dentro del fichero.

Su formato es el siguiente:
long ftell(FILE *pfichero);

El valor que nos da ftell puede ser usado por fseek para volver a la posición actual.

[Arriba]

fprintf y fscanf

Estas dos funciones trabajan igual que sus equivalentes printf y scanf. La única diferencia es que podemos especificar el fichero sobre el que operar (si se desea puede ser la pantalla para fprintf o el teclado para fscanf).

Los formatos de estas dos funciones son:

int fprintf(FILE *pfichero, const char *formato, ...);
int fscanf(FILE *pfichero, const char *formato, ...);

[Arriba]

Ejercicios

En preparación.

[Arriba]

[Anterior] [Siguiente] [Contenido]

© Gorka Urrutia

www.elrincondelc.com