Programación con ficheros¶
La equivalencia entre entrada/salida a través de teclado y pantalla y la utilización de ficheros es muy profunda.
Los S.O. actuales hacen un tratamiento unificado de estos recursos y tratan, por ejemplo, a la pantalla y al teclado como ficheros de salida y de entrada respectivamente, ficheros que están siempre listos para ser utilizados. Es una muestra más del mecanismo de abstracción mencionado anteriormente.
Recalquemos que cuando en C++ usamos cout
,
estamos escribiendo datos en el fichero por defecto o estándar,
la pantalla, y que cuando empleamos cin
,
estamos leyendo datos del fichero por defecto o estándar, el teclado.
Cuando no usamos los ficheros estándar, tanto en C++ como en cualquier otro lenguaje de programación, debemos realizar algunas tareas adicionales:
Abrir el fichero: hay que asociar el fichero (definido a nivel del S.O.) con un objeto que provea la fuente de datos y definir si se va utilizar para entrada o para salida de datos, es decir, para leer o para escribir.
Cerrar el fichero: una vez finalizada la interacción con el objeto que representa el fichero, este hecho debe ser informado al S.O. mediante los métodos apropiados. Así, el S.O. podrá realizar las acciones requeridas para garantizar que el fichero queda en un estado consistente y seguro.
Nótese que el programador no tiene que preocuparse de la naturaleza física del medio de almacenamiento.
El concepto de flujo de datos (stream)¶
Las operaciones de lectura/escritura hacen uso del concepto de flujo o corriente de datos (stream). El símil se basa en el hecho de interpretar la entrada/salida como una corriente o río de datos, donde estos son representados por la aparición en serie, uno tras otro, de los bytes que representan cada uno de los valores transferidos.
El concepto de transferencia de datos en serie es clave.
Si desde el teclado queremos introducir el número 543
,
es evidente que antes de escribir el 3
,
debemos escribir el 4
y antes el 5
.
En el caso de los ficheros se utiliza el mismo paradigma,
se escribe un dato siempre a continuación del anterior.
La naturaleza en serie de los flujos de datos es muy relevante:
no se puede acceder de forma directa (random access) a
los datos del fichero, como
ocurre cuando leemos o escribimos en un elemento de un vector
usando el operador de indexación []
.
Memoria intermedia (buffers)¶
La entrada/salida desde/hacia ficheros está mediada, de forma transparente al programador, por el uso de áreas de la memoria RAM, conocidas como búferes (buffers).
Los búferes cumplen distintos cometidos, pero el fundamental es el de servir como pulmón de la CPU. Dado que los procesos de lectura/escritura en los dispositivos son mucho más lentos que los realizados en la RAM, los datos son temporalmente leídos/escritos en búferes. De esta forma, los accesos a un dispositivo lento no ralentizan las aplicaciones.
Además, este método de trabajo reduce los accesos al disco, con el único inconveniente de que una terminación anormal del programa puede provocar la pérdida de los datos.
Finalmente, aunque nosotros no lo vamos a estudiar en la asignatura, una vez que el fichero o parte de él está en un búfer en memoria, podemos utilizar acceso directo a datos intermedios.
Necesidad de cerrar el fichero¶
Cuando nuestro programa ha terminado de utilizar un fichero debe cerrarlo.
¿Por qué es necesario cerrar el fichero?
La escritura/lectura se realiza sobre los búferes y estos son eventualmente transferidos al medio físico. Cuando se cierra el fichero, se fuerza a realizar esa transferencia. De otro modo, se podría incurrir en pérdida de información.
La utilización de un fichero puede comportar un consumo importante de memoria del ordenador (búferes y otros elementos). Si no se cierra el fichero, esa memoria permanece bloqueada, sin uso, y, por tanto, inutilizada.
El Sistema Operativo establece un número máximo de ficheros que pueden estar abiertos simultáneamente a cargo de una aplicación. Si no cerramos los ficheros que, de momento, no estamos utilizando, puede que nuestro programa no pueda abrir otros que sí son necesarios.