Cuando trabajamos con archivos en C, es fundamental entender cómo se maneja el cursor, ese indicador que nos muestra dónde se va a leer o escribir en el archivo. Este cursor funciona de manera similar a la línea parpadeante que vemos en un editor de texto, señalando la posición actual dentro del archivo. Para manipularlo y obtener información sobre su ubicación, contamos con funciones muy útiles como ftell y fseek.
La función ftell nos permite conocer la posición actual del cursor dentro del archivo. Recibe como parámetro el descriptor del archivo y devuelve un valor de tipo long que indica la posición en bytes desde el inicio del archivo. Por ejemplo, si abrimos un archivo en modo lectura, el cursor estará al principio y ftell devolverá cero. En cambio, si abrimos el archivo en modo append, el cursor se posicionará al final, y ftell nos devolverá el tamaño del archivo en bytes, que corresponde a la posición del cursor. Es importante tener en cuenta que si ftell devuelve -1, significa que ha ocurrido un error al obtener la posición.
Para ilustrar cómo funciona ftell, podemos leer un archivo carácter a carácter con fgetc y, en cada iteración, imprimir la posición actual del cursor junto con el carácter leído. Esto nos permite ver cómo avanza el cursor a medida que recorremos el archivo.
Por otro lado, la función fseek nos da la capacidad de mover el cursor a una posición específica dentro del archivo. Esta función recibe tres parámetros: el descriptor del archivo, un desplazamiento (offset) y un modo que indica desde dónde se realiza ese desplazamiento. Los modos posibles son SEEK_SET, que mueve el cursor a una posición relativa al inicio del archivo; SEEK_END, que lo mueve relativo al final del archivo; y SEEK_CUR, que lo mueve relativo a la posición actual del cursor. Por ejemplo, con fseek(file, 5, SEEK_SET) posicionamos el cursor en el byte número 5 desde el inicio, mientras que con fseek(file, -5, SEEK_END) lo colocamos cinco bytes antes del final.
Una aplicación práctica de estas funciones es calcular el tamaño de un archivo. Para ello, abrimos el archivo en modo lectura, usamos fseek para mover el cursor al final (SEEK_END), luego llamamos a ftell para obtener la posición actual, que corresponde al tamaño en bytes, y finalmente usamos rewind para regresar el cursor al inicio del archivo. La función rewind es equivalente a llamar a fseek con desplazamiento cero y modo SEEK_SET.
Sin embargo, hay que tener precaución con este método cuando trabajamos con archivos de texto en sistemas Windows. Esto se debe a que los saltos de línea en Windows se representan con dos caracteres (\r\n), mientras que en otros sistemas suelen ser solo uno (\n). Los runtimes de C en Windows suelen interpretar estos dos caracteres como un solo salto de línea al leer el archivo, lo que puede hacer que la posición del cursor reportada por ftell no coincida con el tamaño real en bytes del archivo. Para evitar este problema, es recomendable abrir el archivo en modo binario (rb), lo que desactiva esta interpretación y permite que ftell y fseek funcionen correctamente para calcular tamaños y posicionar el cursor.
En resumen, ftell, fseek y rewind son herramientas esenciales para controlar la posición del cursor en archivos, especialmente cuando trabajamos con archivos binarios o necesitamos manipular la lectura y escritura de manera precisa. No obstante, debemos ser conscientes de las particularidades del sistema operativo y el modo en que abrimos los archivos para evitar resultados inesperados.