Make your own free website on Tripod.com

Ficheros en Delphi.

La verdadera potencia de un ordenador reside en su capacidad de tratamiento de datos. Pero no tiene ningun sentido sino podemos almacenar los datos, ya que entonces cada vez que necesitaramos hacer algo deberiamos introducir los datos, y además no podriamos conservar los resultados.

En Delphi podemos tratar ficheros tanto en Ascii como en binario. Los ficheros que vamos a tratar son sequenciales, ya que para almacenar datos en otras estructuras mejores, como estrucutras indexadas, tenemos las bases de datos como Dbase o Paradox, entre otras, las cuales Delphi maneja a la perfección.

Ficheros Ascii

Los ficheros en formato Ascii son las más sencillo de todos. Un clásico fichero Ascii en el Config.sys o el Autoexec.bat, o casi cualquier Script de configuración de cualquier dispositivo. Son ficheros que se pueden visualizar con la orden type del Msdos, o con el Notepad de Windows, suelen llevar extension txt.

Para leer o escribir un fichero de este tipo los primero que tenemos que hacer es indicar que se trata de un fichero de tipo texto, luego crearemos una variable con la cual leeremos o escribiremos, y como estamos tratando ficheros de tipo ascii, esta tendra que ser una cadena de caracteres (un string). Lo siguiente es indicarle a Delphi como se llama nuestro fichero y con que nombre se conocerá en el programa.Luego lo abrimos, hay tres formas de hacerlo, en modo lectura, en modo escritura para añadir, o en modo reescritura. El modo lecutra no tiene nada que comentar, en cambio los otros dos modos tienen su peculiaridad, así en modo escritura abrimos un fichero para añadir cadenas a él, y el modo reescrituta crea el fichero y si este ya existiera con anterioridad seria sobreescrito, así que mucho cuidado.

Vamos a crear un ejemplo donde introduzcas tu nombre y este sea grabado en un fichero de texto. Para ello pon un componente Edit y un botón en un formulario y asocia este código a su evento Onclik.

procedure TForm1.Button1Click(Sender: TObject);

Var
MiFichero : TextFile;
Nombre : String;
begin
Nombre := Edit1.Text;
AssignFile (MiFichero,'nombre.txt');
Rewrite (MiFichero);
writeln(MiFichero,Nombre);
CloseFile (mifichero);
end;

Si pruebas este programa verás que por muchos nombre que metas solo el último es grabado, el motivo es que cada vez que invocas este procedimiento el fichero es abierto con la instrucción Rewrite, la cual crea el fichero sin importarle si existe o no. Observa la secuencia de las instrucciones, dentro de la sección de la variables lo importante es la asignación es la variable TextFile, la cual determina el tipo de fichero que vamos a utilizar. Dentro del bloque de instrucciones tenemos la instruccion AssignFile, que es para indicar como se llama el fichero de texto que vamos a usar, y lo asigna a Mifichero, que es el nombre con el que será conocido de ahora en adelante. Luego lo abrimos con la orden Rewrite, la cual ya os comenté que crea el fichero exista o no exista. Después grabamos los datos en nuestro fichero con la orden Writeln indicando que lo grabamos en nuestro fichero, ya que podemos tener más de un fichero abierto y de diferentes tipos, sin queremos grabar más cosas debemos hacerlo antes de cerrar el fichero, ya que sino cuando lo volvamos a abrir este se creará.

Yo he usado la orden writeln, que graba una cadena de caracteres con un retorno de carro al final, con lo que si grabáramos otra cadena de caracteres esta se grabaría en la línea de abajo. En cambio si usas la orden Write, no es graba la cadena con el retorno de carro al final, con lo que si grabas otra cadena de caracteres esta sería grabada a continuación. Prueba a cambiar la orden y ver las diferencias en el fichero creado.

Para leer el fichero, el proceso es similar, la diferencia está en que no podemos usar una orden de escritura sino que debemos usar una de lectura. Coloca un nuevo botón en el proyecto que estamos construyendo y una etiqueta, dentro del manejador Onclick del botón escribe lo siguiente:

procedure TForm1.Button2Click(Sender: TObject);
Var
MiFichero : TextFile;
Nombre : String;
begin
AssignFile (MiFichero,'nombre.txt');
Reset (MiFichero);
Read(MiFichero,Nombre);
CloseFile (mifichero);
Label1.Caption := Nombre;
end;

Prueba el programa, y verás que después de haber grabado el nombre, este es leido. Pero ten encuenta que si tratas de abrir un fichero para leer, y este no existe obtendrás un error. Para controlar este error lo primero que se te puede venir a la cabeza es preguntar si existe el fichero primero, lo cual estaría bien si decides tomar medidas al respecto, como puede ser crearlo, pero si solo deseas controlar el error, y evitar un mensaje en inglés lo puedes hacer con las instrucciones Try Except, las cuales explique en el capítulo de errores. Esta última opción es la que tomé yo en el programa de ejemplo que acompaña a esta página.
Para preguntar si existe un fichero debes usar la función FileExists, la cual devuelve True en el caso de que exista el fichero, la manera de usarla es como sigue:
If FileExists ('Nombre.txt') Then
showmessage ('El fichero existe')
Else
Showmessage ('El fichero no existe');

Para recorrer un fichero (del tipo de sea), existe la orden Seek, la cual avanza por el fichero, en el caso de un fichero de texto la orden ReadLn avanza línea a línea, haciendo el mismo efecto. Seek, esta orientado más a fichero de tipo binario, lo veremos más adelante, aunque repito que la orden de lectura ya avanza el puntero de lectura.Para ilustrarlo mejor, desde una aplicación nueva, vamos hacer un programa que cuente el número de veces que aparece la palabra Rem, en el autoexec.bat de tu sistema.
Coloca y botón, y dos etiquetas, una con el texto:"Número de rem:", y la otra la pones a continuación y sin texto. Ahora en evento Onclik del botón situa este código.

procedure TForm1.Button1Click(Sender: TObject);
Var
Fichero : TextFile;
Linea : String;
Contador: Integer;
begin
Contador := 0;
AssignFile (Fichero,'c:\autoexec.bat');
Reset (Fichero);
While Eof(Fichero) = False Do
Begin
Readln(Fichero,Linea);
If Pos ('rem ',lowerCase(Linea)) > 0 Then
Inc (Contador);
End;
CloseFile (Fichero);
Label2.Caption := IntToStr (Contador);
End;

Un detalle, a la hora de gestionar fichero, es la manera de construir el bucle que recorre el fichero. Esta hecho con un While, también se podía hacer con un repeat until. La diferencia radica en que un while comprueba la condición antes de entrar en el bucle, y un repeat ejecuta el bloque y luego comprueba la condición con lo cual por lo menos una vez en leido el fichero. Pero que pasa, si el fichero esta vacio, pues que la mejor decisión es averiguar si el fichero esta vacio antes de leer nada, y evitarme trabajo inutil, y quizas sorpresas, por eso el bucle esta hecho con un While.He usado una función que es Pos la cual devuelve valores según encuentre una cadena dentro de otra. Así en el ejemplo si la cadena Rem esta dentro de la línea que hemos leido, pues el valor devuelto será mayor de cero, siendo este el valor del delplazamiento dentro de la cadena. Esto viene a que Delphi (por lo menos en la versiones de 32 bits) con sidera las cadenas como un tabla Matriz unidimensional, donde cada caracter puede ser leido por su posición, empezando por uno, ya que el supuesto caracter cero contiene infomación usada por Delphi para almacernar la cadena. Entonces si en una cadena quieres leer el caracter que esta en la posición 2 puedes hacer esta asignación:
Caracter := Cadena [2];
Ojo que si lees más alla de la longuitud de la cadena Dios sabe que devolverá el sistema, así que para saber la longuitud de una cadena usa Lenght (cadena), que devuelve la longuitud de la cadena.
Otra función que he usado es LowerCase, la que convierte toda a minusculas una cadena, lo hago para asegurarme que lo que haya en la cadena este en minusculas y así el posible rem que busco coincida. También se podia hacer al revés con UpperCase, que convierte a mayusculas una cadena.
Por último la última función que he usado es IntToStr, que convierte un número entero a cadena, esta función genera un error si no es posible. Tiene un primo cercano que es StrToInt, que convierte de Cadena a entero.
Creo que no hace falta comentar que Inc(contador) en lo mismo que Contador := Contador +1. Ten en cuenta que Inc solo se permite con variables numéricas no con propiedades.

La tercera forma de abrir un fichero es para añadir datos, para lo cual debes usar Append (fichero), en lugar de Read o Write. Append abre un fichero existente para escribir en él, y todo lo que escribas lo hace al final de este. La mecánica es identica a los ejemplo anteriores.

Ficheros Binarios.

Los ficheros binarios son todo lo contrario a los Ascii, en el sentido que no pueden ser leido con un Type, o con un procesador de Texto, solo pueden ser leidos por el programa que los haya creado, o en su defecto uno que haya sido programado para leerlos. Para poder trabajar con ellos debemos leer/escribir bytes, si queremos podemos definir un escructura, la cual nos servirá para leer un serie de Bytes seguidos, y así poder interpretar la información y manejarla con mayor soltura.

La ventaja es que tenemos dos de funciones que no habia en los fichero anteriores, como son Filesize, y FilePos. Un ejemplo puede ser el siguiente, en un formulario coloca un botón, una etiqueta, y un campo Edit, de nuevo en el manejador Onclik del botón coloca los siguiente:
procedure TForm1.Button1Click(Sender: TObject);
Var
Fichero : File Of Byte;
Valor : Byte;
begin
AssignFile (Fichero,Edit1.text);
Reset (Fichero);
Seek(Fichero,11);
Read (Fichero,Valor);
CloseFile (Fichero);
Label1.Caption := IntToStr (Valor);
end;

Lo que conseguinos con este fichero es leer el Byte 12 de un fichero que hemos introducido su nombre en el campo Edit. He dicho byte 12 porque se cuentan desde 0.

Lo interesante de este sistema es poder crear un fichero binario con un tipo de datos determinado por nosotros, para lo cual debemos declarar una estructura de datos, luego indicar que el fichero debe usar ese registro y todo solucionado. Para ello debes declarar la estructura al principio de la unidad, justo despues de la cláusula uses y la declaración del formulario. Yo he declarado un registro como el que sigue:
Type TMiRegistro = Record
Nombre : String [20];
Telefono : String [7];

End;
He hecho este registro porque vamos hacer un ejemplo para grabar unos datos en fichero. En un formulario coloca dos etiquetas, un botón y un par de campos edit, como la imagén que hay debajo de este parrafo.

{short description of image}

Debes tener en cuenta que al crearse el formulario es el momento de abrir el fichero, y cuando la apliacación se cierra debes cerrar el fichero. Y como no, en el evento Onclick del botón pondremos las ordenes necesarias para grabar los datos.Así el código fuente de los tres eventos queda como sigue.
procedure TForm1.FormCreate(Sender: TObject);
begin
AssignFile (Fichero,'Datos.dat');
Rewrite (Fichero);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
With MiRegistro Do
Begin
Nombre := Edit1.Text;
Telefono := Edit2.Text;
End;
Write (Fichero,MiRegistro);
end;
procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
CloseFile (Fichero);
end;

Fijate que no he declarado las variables dentre de ningun procedimiento, sino que lo he hecho en la sección Private de la unidad, para que así esten disponibles en todos los procedimientos. Estas son las declaraciones de la seccion Private:
private
{ Private declarations }
MiRegistro : TMiRegistro;
Fichero : File of TMiRegistro;

He construido un programa a parte que lee los datos creados por este programa. Su estructura es casi idéntica, piensa lo que cambiaria y como lo harias. Depués hechale un vistazo al código fuente de este programa que esta en el fichero Zip, junto con los otros ejemplos que he planteado, se llama Leer.dpr.

La principal función, a mi modo de ver, de los ficheros binarios es el de almacenar algún tupo de datos que se leen secuencialmente y sirven para un motivo en concreto dentro de un programa. Porque si quieres almacenar datos en general, y gestionarlos eficazmente pues es mejor usar una base de datos. Incluso yo le veo más uso a los ficheros de texto (ascii) ya que siempre se usan para los Scripts, o los ini, aunque Delphi presenta una forma de leer y escribir los ficheros ini, muy efectiva que veremos más adelante. En el próximo capítulo veremos como leer y escribir un fichero de texto con un control de Delphi, el cual es un pequeño editor de texto, así como usar los cuadros de dialogo standar de windows para abrir o cerrar un fichero, y espero que alguna sorpresa, depende del tiempo que tenga.