03 septiembre 2007

Trabajando con archivos de texto y binarios (y V)

Vamos a terminar de ver los recursos de los que dispone Delphi para el tratamiento de archivos.

PARTIENDO UN ARCHIVO EN DOS

En este ejemplo vamos a coger el archivo prueba.dat de 100 Kb y dejamos sólo las primeras 30 Kb eliminando el resto:

procedure TFormulario.PartirArchivo;
var F: File of byte;
Buffer: array[0..1023] of Byte;
i: Integer;
begin
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'prueba.dat' );
Reset( F );

// Leemos 30 Kb utilizando un buffer de 1 Kb
for i := 1 to 30 do
BlockRead( F, Buffer, 1024 );

Truncate( F );
CloseFile( F );
end;

Hemos utilizado para ello la función Truncate, la cual parte el archivo que estamos leyendo según donde este el puntero F.


ASEGURANDO QUE SE GUARDE LA INFORMACIÓN EN ARCHIVOS DE TEXTO

Cuando abrimos un archivo de texto para escribir en él no se guarda completamente toda la información hasta que se cierra con el procedimiento CloseFile. Esto puede dar problemas si en algún momento el procedimiento WriteLn provoca un error dejando el archivo abierto. Se perdería la mayor parte de la información que supuestamente debería haberse guardado en el mismo.

Para evitar esto disponemos de la función Flush:

function Flush( var t: TextFile ): Integer;

Esta función lo que hace es vaciar el buffer del archivo de texto en el disco duro. Es algo así como ejecutar CloseFile pero sin cerrar el archivo. Por ejemplo:

var
F: TextFile;
sArchivo: String;
begin
sArchivo := ExtractFilePath( Application.ExeName ) + 'prueba.txt';
AssignFile( F, sArchivo );
Rewrite( F );
WriteLn( F, 'Esto es el contenido del archivo de texto.' );
Flush( F );
// aquí podemos seguir escribiendo en el mismo
CloseFile( F );
end;

GUARDANDO OTROS TIPOS DE DATOS EN LOS ARCHIVOS

Hasta ahora sólo hemos guardado información de tipo texto y binaria en archivos pero se puede guardar cualquier tipo de información utilizando cualquier tipo de dato. Por ejemplo para guardar una serie de números reales se haría de la siguiente manera:

procedure TFormulario.GuardarRecibos;
var
F: File of Real;
r: Real;
begin
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'ImporteRecibos.dat' );
Rewrite( F );
r := 120.45;
Write( F, r );
r := 1800.05;
Write( F, r );
r := 66.31;
Write( F, r );
CloseFile( F );
end;

Si os fijais bien en el archivo resultante vemos que ocupa 24 bytes. Esto es así porque el tipo real ocupa 8 bytes en memoria y como son 3 números reales lo que hemos guardado entonces hace un total de 24 bytes. Hay que asegurarse de que tanto al leer como al guardar información en este tipo de archivos se haga con el mismo tipo de variable. Si guardamos información con File of Real y la leemos con File of Single los resultados podrían ser catastróficos (a parte de quedarse el archivo a medio leer).

También se pueden guardar estructuras de datos almacenadas en registros. En este ejemplo que voy a mostrar vamos a ver como guardar los datos de un cliente en un archivo:

type
TCliente = record
ID: Integer;
sNombre: String[50];
rSaldo: Real;
bPagado: Boolean;
end;

procedure TFPrincipal.CrearArchivoRegistro;
var
Cliente: TCliente;
F: File of TCliente;
begin
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'clientes.dat' );
Rewrite( F );

with Cliente do
begin
ID := 1;
sNombre := 'FRANCISCO MARTINEZ LÓPEZ';
rSaldo := 1200.54;
bPagado := False;
end;

Write( F, Cliente );

with Cliente do
begin
ID := 2;
sNombre := 'MARIA ROJO PALAZÓN';
rSaldo := 622.32;
bPagado := True;
end;

Write( F, Cliente );

CloseFile( F );
end;

Unas de las cosas a tener en cuenta es que cuando se define una estructura de datos no se puede definir una variable de tipo String sin dar su tamaño, ya que cada registro debe tener una longitud fija. Si ponemos String nos da un error al compilar, por eso hemos puesto en el nombre un String[50].

Con esto finalizamos la parte básica de tratamiento de archivos en Delphi.

Pruebas realizadas en Delphi 7.

Publicidad