9.4)Archivos de Texto.Ya hemos dicho que un archivo es un conjuntos de bytes secuenciales terminados con el carácter especial EOF . En los archivos de texto, estos bytes son interpretados como caracteres. Toda la información que se almacena en un archivo de texto son caracteres. Esto quiere decir, entre otras cosas, que toda la información almacenada en un archivo de texto puede ser visualizada por un procesador de textos o un editor cualquiera, de la misma manera que se visualiza la información de un archivo que contiene un programa fuente de C.
'H' 'O' 'L' 'A' ........ EOF 9.4.1)Archivos de Acceso Secuencial.
9.4.1.1)Apertura y cierre de Archivos de Acceso Secuencial.
Los archivos, sean de texto o binarios, de acceso secuencial o aleatorio, es necesario abrirlos antes de extraer o introducir datos. Y no sólo eso, después de llevar a cabo todas las operaciones de lectura/escritura sobre ellos es obligatorio cerrarlos, de lo contrario puede perderse toda la información contenida en ellos.Así pues, la primera operación que habrá que realizar siempre que se desee trabajar con un archivo será la operación de apertura del mismo. La especificación de la función de apertura es:
donde:FILE *fopen(char *pathname, char *type)Los archivos se referencian dentro del programa mediante su nombre, pero esto se hace únicamente en la apertura del archivo. A partir del momento en que el archivo ha sido abierto, éste se manipulará dentro del programa a través de un descriptor de fichero, un puntero de un tipo especial llamado FILE que devuelve la función fopen y que está definido en el archivo de cabecera <stdio.h>.
- pathname indica el nombre del fichero y la ruta de acceso.
- type indica el modo de apertura del archivo.
Modo de Apertura Significado "a" Abre el fichero para añadir datos al final del fichero. Si el fichero no existe, se crea. "r" Abre el fichero para lectura.El fichero debe existir. "w" Abre el fichero para escritura.Los datos se escriben desde el principio. Si el fichero no existe, se crea. "a+" Abre el fichero para lectura y para añadir datos al final del mismo. Si el fichero no existe, se crea. "r+" Abre el fichero para lectura y escritura. Los datos se escriben desde el principio y el fichero debe existir. "w+" Abre el fichero para lectura y escritura. Los datos se escriben desde el principio y si el fichero no existe se crea. Respecto a esta tabla habría que hacer algunas consideraciones:
- Las lecturas sólo podrán hacerse desde el principio del archivo, mientras que las escrituras podrán hacerse desde el principio (modos "w", "w+") o añadiendo datos al final (modos "a", "a+").
- La fución fopen puede dar error por intentar abrir un fichero que no existe mediante "r" o "r+", por no existir espacio en disco para crear archivo... En estos casos, fopen devuelve NULL. Habrá que intentar comprobar si se ha producido error en la apertura del archivo (lo veremos más adelante).
9.4.1.2)Lectura y Escritura de Archivos de Acceso Secuencial.
En primer lugar se va a ver la lectura y escritura de datos de tipo carácter. Un carácter puede ser leído de un archivo (abierto previamente con el modo adecuado para permitir leer de él) mediante la función getc:
La función getc tiene como único argumento el descriptor de fichero pf y devuelve el carácter leído del fichero en forma de entero sin signo. El hecho de que la función devuelva un entero carece de importancia desde el punto de vista práctico ya que, al realizar la asignación a una variable de tipo char, se realiza la conversión de tipo automáticamente.int getc(FILE *pf)Dado que los archivos son de acceso secuencial, tras la apertura del fichero, el carácter devuelto por getc será el primer carácter del archivo. Si se vuelve a utilizar la función getc, el carácter devuelto será el siguiente y así sucesivamente.
El descriptor de fichero apunta al primer carácter del archivo cuando éste se abre y apunta al siguiente cada vez que se lee o escribe algun carácter.
Veamos un ejemplo de la lectura de cinco caracteres de un archivo de texto mediante la función getc:
NOTA: Este programa podría dar error si el fichero no tuviera tantos caracteres, es decir, si la lectura alcanzase el carácter de fin de fichero (EOF).
Veamos ahora como podemos leer todos los carácteres de un archivo de texto mediante la función getc.
Se hace una lectura de todo el fichero, sea cual sea el número de carácteres y se muestra por pantalla. En la última iteración del bucle el descriptor de fichero (pf) apunta a EOF, carácter que devolverá evaluándose a 0 la condición del bucle.
De la misma manera que se leen los caracteres de unfichero uno a uno, se pueden escribir en él mediante la función putc:
El primer argumento de putc es el carácter a escribir en el fichero, mientras que el segundo argumento es el descriptor de fichero. Si la escritura es correcta, putc devuelve el carácter escrito, devolviendo EOF en caso contrario.int putc(int c, FILE *pf)Veamos un ejemplo de escritura de una cadena de caracteres en una archivo de texto mediante putc:
Al cerrar el fichero se inserta el carácter EOF y se libera la variable pf.Al igual que es posible leer o escribir caracteres en el fichero de uno en uno, es posible leer o escribir un conjunto de caracteres a la vez. Para esto se utilizan dos funciones análogas a scanf y printf: fscanf y fprintf.
La diferencia entre ellas es que el primer argumento es un descriptor de fichero al hacerse la entrada y la salida de un fichero y no de ningún dispositivo. La sintaxis de ambas es:
donde:int fscanf (FILE *pf, char *format, [pointer, ] );int fprintf (FILE *pf, char *format, [arg, ] );
La función fscanf devuelve el número de items leídos o EOF si se llega al final del fichero, mientras que fprintf devuelve el número de bytes escritos en el fichero o un número negativo en caso de error.
- pf es el descriptor de fichero.
- format es la cadena de caracteres a leer o a escribir.
- [pointer, ] representa la lista opcional de punteros a variables donde se almacenarán los datos leídos y que vienen especificados en la cadena format.
- [arg, ] representa la lista opcional de variables cuyos valores se van a escribir en el fichero, también especificados en format.
El funcionamiento de fscanf es exactamente igual al de scanf (puede leer cadenas separadas por espacios y otros caracteres especiales). De la misma manera el funcionamiento de fprintf es el mismo que el de printf (escribe la cadena hasta encontrar el retorno de carro o el final de la cadena).
Veamos un ejemplo de escritura en un fichero de texto de una cadena de caracteres (puede contener blancos) mediante la función fprintf:
Veamos un ejemplo en el que se lee una cadena de caracteres de un archivo de texto mediante la función fscanf. Supondremos que la ciudad que se introduce por teclado, es almacenada en el fichero "FICHERO.DAT", para posteriormente ser leído con fscanf:NOTA: Comprobar que el programa no permite leer cadenas separadas por espacios.
Si quisiéramos leer cadenas completas de caracteres incluidos los blancos con la función fscanf, abría que colocar la función dentro de un bucle. Veamos un ejemplo:
Una alternativa para leer cadenas completas es la función fgets, de funcionamiento análogo a gets:
La función fgets lee n caracteres del fichero apuntado por pf o hasta que encuentre el caracter de fin de linea o retorno de carro. Introduce los caracteres en la cadena s, además de el carácter de retorno de carro ('\n') y el carácter de final de cadena.char *fgets (char *s, int n, file *pf);
Veamos un ejemplo que aclara la utilización
de fgets. Es similar al utilizado para explicar fscanf, pero ahora el programa
no va a permitir leer una cadena separada por espacios.
Veamos un ejemplo de escritura de datos
de distintos tipos en un fichero mediante fprintf:
9.4.2)Archivos de Acceso Aleatorio.
La utilización de ficheros de acceso secuencial sólo permite leer datos desde el principio del fichero o escribir datos al principio o al final del mismo. Es necesario introducir nuevos mecanismos para tener la posibilidad de acceder a posiciones intermedias de un fichero.El acceso directo a cualquier dato de un fichero es posible realizarlo mediante la utilización de archivos de acceso aleatorio, o más bien, mediante la utilización del modo de acceso aleatorio ya que los ficheros son los mismos. Todas las operaciones vistas para el manejo de ficheros de acceso secuencial son válidas para los archivos de acceso aleatorio. El único elemento nuevo que se incorpora en este tipo de acceso a ficheros es una función capaz de posicionar el puntero del fichero que devuelve la función fopen en distintas partes del fichero para acceder a datos intermedios.
El tipo FILE es una estructura que contiene varios campos, uno de los cuales contiene el número de byte al que se está apuntando en un momento dado de la ejecución del programa. Cuando se abre un fichero para lectura, el campo mencionado de la variable pt declarada de tipo FILE es 0, indicando de esta manera que la primera lectura que se haga será del primer byte. A medida que se van leyendo bytes, el valor de dicho campo se va incrementando.
La función fseek( ) permite modificar el valor del puntero pf para que apunte a cualquier byte del fichero y tener de esta manera un acceso aleatorio. El manejo de archivos de acceso aleatorio no implica más que añadir la nueva función fseek a las ya existentes para archivos de acceso secuencial. Su especificación es la siguiente:
donde:fseek(FILE *pf, long int desplazamiento, int modo)
- pf: es el puntero o descriptor de fichero,
- desplazamiento: es el desplazamiento en bytes a efectuar,
- modo: es el punto de referencia que se toma para efectuar dicho desplazamiento. En el fichero de cabecera <stdio .h> hay tres constantes definidas:
SEEK_SET (0)
SEEK_CUR (1)
SEEK_END (2)
Los valores entre paréntesis indican su valor. El tercer parámetro (modo) de la función fseek puede contener una cualquiera de las constantes simbólicas indicando que el desplazamiento se hará a partir del principio del fichero (SEEK_SET), a partir del la posición actual de pf (SEEK_CUR) o a partir del final del fichero (SEEK_END).Para el siguiente ejemplo supondremos que el fichero "FICHERO.DAT", contiene la cadena "ESTE ES EL TEXTO DEL FICHERO", y veremos como leer diversas palabras del mismo: