Universidad Carlos III de Madrid

Grado en Ing. Telemática/Sist. Audiovisuales/Sist. de Comunicaciones

Arquitectura de Sistemas

Septiembre 2012 - Enero 2013

2. Funciones básicas

Vamos a centrarnos en cómo abrir y cerrar ficheros y en cómo interpretar los mensajes de error que pueden dar estas dos operaciones.

2.1. Punteros a FILE

La estructura FILE es la estructura que controla los ficheros y se encuentra en la cabecera stdio.h. Los flujos utilizan estos punteros a ficheros para realizar las operaciones E/S. La siguiente línea de código declara una variable de tipo puntero a fichero:

FILE *ptr_fich;

En la estructura FILE es donde se encuentra el atributo que representa el indicador de posición de fichero.

2.2. Abriendo un fichero

La función fopen abre un fichero y lo asocia a un flujo. Necesitas especificar como argumentos el nombre de ese fichero (o la ruta y el nombre) y el modo de apertura.

#include <stdio.h>
FILE *fopen(const char *filename, const char *mode);

Aquí filename es un puntero a char que referencia un string con el nombre del fichero. mode apunta a otro string que especifica la manera en la que se va a abrir el fichero. La función fopen devuelve un puntero de tipo FILE. Si ha ocurrido algún error al abrirse, devuelve NULL.

El parámetro mode es una combinación de los caracteres r (read, lectura), w (write, escritura), b (binario), a (append, añadir), y + (actualizar). Si usas el caracter a y el fichero existe, el contenido de ese fichero se mantiene y los datos nuevos se añaden justo al final, tras el último dato que ya estuviera escrito (el indicador de fichero pues no está situado al inicio del fichero, sino que en este caso está al final). Si el fichero no existe, lo crea. Con w es diferente; este modo siempre borra los datos del fichero si existe (si no, crea uno nuevo). Si al modo le añades el +, permite que el fichero se abra para escritura o lectura y puedes modificar cualquier dato que hubiera en él. Si usas r, el fichero debe existir; si no, fopen dará error y te devolverá NULL.

La siguiente lista muestra los posibles modos de abrir un fichero:

  • "r" abre un fichero de texto existente para lectura.

  • "w" crea un fichero de texto para escritura.

  • "a" abre un fichero de texto existente para añadir datos.

  • "r+" abre un fichero de texto existente para lectura o escritura.

  • "w+" crea un fichero de texto para lectura o escritura.

  • "a+" abre o crea un fichero de texto para añadirle datos.

  • "rb" abre un fichero binario existente para lectura.

  • "wb" crea un fichero binario para escritura.

  • "ab" abre un fichero binario existente para añadir datos.

  • "r+b" abre un fichero binario existente para lectura o escritura.

  • "w+b" crea un fichero binario para lectura o escritura.

  • "a+b" abre o crea un fichero binario para añadirle datos.

A veces podrás ver que el modo está escrito como "rb+" en vez de "r+b", por ejemplo, pero es equivalente.

Responde a las siguientes preguntas para ver si has entendido lo que se explica en este documento:

  • ¿Qué hace la siguiente expresión?:

    fopen(“text.bin”, r+b);
    • Abre un fichero existente para lectura y escritura.

    • Crea un fichero binario para lectura y escritura.

    • Abre un fichero existente para lectura y añadir datos al final.

    • Crea un fichero binario para lectura y añadir datos al final.

    • Ninguna de las anteriores.

2.3. Cerrando un fichero

Después de abrir un fichero y leerlo o escribir en él, hay que desenlazarlo del flujo de datos al que fue asociado. Esto se hace con la función fclose, cuya sintaxis es la siguiente:

#include <stdio.h>
int fclose(FILE *stream);

Si fclose cierra bien el fichero, devuelve 0. Si no, la función devuelve EOF. Normalmente sólo falla si se ha borrado el fichero antes de intentar cerrarlo. Acuérdate siempre de cerrar el fichero. Si no lo haces, se pueden perder los datos almacenados en él. Además, si no lo cierras, otros programas pueden tener problemas si lo quieren abrir más tarde.

El siguiente programa abre y cierra un fichero de texto, comprobando los posibles errores que puedan surgir:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <stdio.h>

enum {EXITO, FALLO};
int main(void)
{
  FILE *ptr_fichero;
  char nombre_fichero[] = "resumen.txt";
  int resultado = EXITO;

  if ( (ptr_fichero = fopen(nombre_fichero, "r") ) == NULL) 
  {
    printf("No se ha podido abrir el fichero %s.\n", nombre_fichero);
    resultado = FALLO;
  }
  else 
  {
    printf("Abierto fichero; listos para cerrarlo.\n");
    if (fclose(ptr_fichero)!=0) 
    {
      printf("No se ha podido cerrar el fichero %s.\n", nombre_fichero);
      resultado = FALLO;
    }
  }
  return resultado;
}

2.4. Abriendo un fichero con un descriptor

Para poder abrir un fichero dado su descriptor de fichero ( file descriptor (fd) en inglés) se ha de usar la función fdopen. Esta función se comporta como la función fopen, pero en vez de abrir un fichero dado su nombre, usa el identificador de fichero para abrirlo:

#include <stdio.h>
int fdopen(int fildes, const char *mode);

Una forma de conseguir un descriptor para un fichero es con la función mkstemp:

#include <stdio.h>
int mkstemp(char *template);

Esta función genera un nombre de fichero temporal único a partir del string template. Los últimos seis caracteres de template deben ser “XXXXXX”, que son reemplazados luego por mkstemp con una cadena que hace que el nombre no esté repetido. Ya que será modificada, template no debe ser definida como constante. La función mkstemp devuelve el descriptor de fichero del fichero temporal creado o -1 en caso de error.