11 agosto 2006

Guardando y cargando opciones

Hay ocasiones en que nos interesa que las opciones de nuestro programa permanezcan en el mismo después de terminar su ejecución. Principalmente se suelen utilizar cuatro maneras de guardar las opciones:

1º En un archivo de texto plano.

2º En un archivo binario.

3º En un archivo INI.

4º En el registro del sistema de Windows.

Vamos a suponer que tenemos un formulario de opciones con campos de tipo string, integer, boolean, date, time y real.

Los archivos de opciones se crearán en el mismo directorio en el que se ejecuta nuestra aplicación.

GUARDANDO OPCIONES EN TEXTO PLANO

Para ello utilizamos un archivo de tipo TextFile para guardar la información:

procedure TFPrincipal.GuardarTexto;
var F: TextFile;
begin
// Asignamos el archivo de opciones al puntero F
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'opciones.txt' );

// Abrimos el archivo en modo creación/escritura
Rewrite( F );

// Guardamos las opciones
WriteLn( F, IMPRESORA.Text );
WriteLn( F, IntToStr( COPIAS.Value ) );

if VISTAPREVIA.Checked then
WriteLn( F, 'CON VISTA PREVIA' )
else
WriteLn( F, 'SIN VISTA PREVIA' );

WriteLn( F, DateToStr( FECHA.Date ) );
WriteLn( F, HORA.Text );
WriteLn( F, FormatFloat( '###0.00', MARGEN.Value ) );

CloseFile( F );
end;

CARGANDO OPCIONES DESDE TEXTO PLANO

Antes de abrir el archivo comprobamos si existe:

procedure TFPrincipal.CargarTexto;
var F: TextFile;
sLinea: String;
begin
// Si no existe el archivo de opciones no hacemos nada
if not FileExists( ExtractFilePath( Application.ExeName ) + 'opciones.txt' ) then
Exit;

// Asignamos el archivo de opciones al puntero F
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'opciones.txt' );

// Abrimos el archivo en modo lectura
Reset( F );

// Cargamos las opciones
ReadLn( F, sLinea );
IMPRESORA.Text := sLinea;

ReadLn( F, sLinea );
COPIAS.Value := StrToInt( sLinea );

ReadLn( F, sLinea );
VISTAPREVIA.Checked := sLinea = 'CON VISTA PREVIA';

ReadLn( F, sLinea );
FECHA.Date := StrToDate( sLinea );

ReadLn( F, sLinea );
HORA.Text := sLinea;

ReadLn( F, sLinea );
MARGEN.Value := StrToFloat( sLinea );

CloseFile( F );
end;

GUARDANDO OPCIONES EN UN ARCHIVO BINARIO

Lo que hacemos en esta ocación es crear un registro (record) que contenga las opciones de nuestro programa. Después volcamos todo el contenido del registro en un archivo binario del mismo tipo.

En la interfaz de nuestra unidad definimos:

type
TOpciones = record
sImpresora: String[100];
iCopias: Integer;
bVistaPrevia: Boolean;
dFecha: TDate;
tHora: TTime;
rMargen: Real;
end;

Y creamos el procemimiento que lo graba:

procedure TFPrincipal.GuardarBinario;
var
// Creamos un registro y un fichero para el mismo
Opciones: TOpciones;
F: file of TOpciones;
begin
// Metemos las opciones del formulario en el registro
Opciones.sImpresora := IMPRESORA.Text;
Opciones.iCopias := COPIAS.Value;
Opciones.bVistaPrevia := VISTAPREVIA.Checked;
Opciones.dFecha := FECHA.Date;
Opciones.tHora := StrToTime( HORA.Text );
Opciones.rMargen := MARGEN.Value;

// Asignamos el archivo de opciones al puntero F
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'opciones.dat' );

// Abrimos el archivo en modo creación/escritura
Rewrite( F );

// Guardamos de golpe todas las opciones
Write( F, Opciones );

// Cerramos el fichero
CloseFile( F );
end;

CARGANDO OPCIONES DESDE UN ARCHIVO BINARIO

Utilizamos el registro creado anteriormente:

procedure TFPrincipal.CargarBinario;
var
// Creamos un registro y un fichero para el mismo
Opciones: TOpciones;
F: file of TOpciones;
begin
// Asignamos el archivo de opciones al puntero F
AssignFile( F, ExtractFilePath( Application.ExeName ) + 'opciones.dat' );

// Abrimos el archivo en modo creación/escritura
Reset( F );

// Guardamos de golpe todas las opciones
Read( F, Opciones );

// Cerramos el fichero
CloseFile( F );

// Copiamos las opciones del registro en el formulario de opciones
IMPRESORA.Text := Opciones.sImpresora;
COPIAS.Value := Opciones.iCopias;
VISTAPREVIA.Checked := Opciones.bVistaPrevia;
FECHA.Date := Opciones.dFecha;
HORA.Text := TimeToStr( Opciones.tHora );
MARGEN.Value := Opciones.rMargen;
end;

GUARDANDO OPCIONES EN UN ARCHIVO INI

Los dos casos anteriores tienen un defecto: si ampliamos el número de opciones e intentamos cargar las opciones con el formato antiguo se puede provocar un error de E/S debido a que los formatos de texto o binario han cambiado.

Lo más flexible en este claso es utilizar un archivo INI, el cual permite agrupar opciones y asignar un nombre a cada una:

procedure TFPrincipal.GuardarINI;
var INI: TIniFile;
begin
// Creamos el archivo INI
INI := TINIFile.Create( ExtractFilePath( Application.ExeName ) + 'opciones.ini' );

// Guardamos las opciones
INI.WriteString( 'OPCIONES', 'IMPRESORA', IMPRESORA.Text );
INI.WriteInteger( 'OPCIONES', 'COPIAS', COPIAS.Value );
INI.WriteBool( 'OPCIONES', 'VISTAPREVIA', VISTAPREVIA.Checked );
INI.WriteDate( 'OPCIONES', 'FECHA', FECHA.Date );
INI.WriteTime( 'OPCIONES', 'HORA', StrToTime( HORA.Text ) );
INI.WriteFloat( 'OPCIONES', 'MARGEN', MARGEN.Value );

// Al liberar el archivo INI se cierra el archivo opciones.ini
INI.Free;
end;

CARGANDO OPCIONES DE UN ARCHIVO INI

Aunque aquí comprobamos si existe el archivo, no es necesario, ya que cargaría las opciones por defecto:

procedure TFPrincipal.CargarINI;
var INI: TIniFile;
begin
// Si no existe el archivo no hacemos nada
if not FileExists( ExtractFilePath( Application.ExeName ) + 'opciones.ini' ) then
Exit;

// Creamos el archivo INI
INI := TINIFile.Create( ExtractFilePath( Application.ExeName ) + 'opciones.ini' );

// Guardamos las opciones
IMPRESORA.Text := INI.ReadString( 'OPCIONES', 'IMPRESORA', '' );
COPIAS.Value := INI.ReadInteger( 'OPCIONES', 'COPIAS', 0 );
VISTAPREVIA.Checked := INI.ReadBool( 'OPCIONES', 'VISTAPREVIA', False );
FECHA.Date := INI.ReadDate( 'OPCIONES', 'FECHA', Date );
HORA.Text := TimeToStr( INI.ReadTime( 'OPCIONES', 'HORA', Time ) );
MARGEN.Value := INI.ReadFloat( 'OPCIONES', 'MARGEN', 0.00 );

// Al liberar el archivo INI se cierra el archivo opciones.ini
INI.Free;
end;

GUARDANDO OPCIONES EN EL REGISTRO DEL SISTEMA

Si queremos que nadie nos toque las opciones del programa podemos guardarlo todo en el registro de Windows:

procedure TFPrincipal.GuardarRegistroSistema;
var Reg: TRegistry;
begin
// Creamos un objeto para manejar el registro
Reg := TRegistry.Create;

// Guardamos las opciones
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey( '\Software\MiPrograma', True ) then
begin
Reg.WriteString( 'IMPRESORA', IMPRESORA.Text );
Reg.WriteInteger( 'COPIAS', COPIAS.Value );
Reg.WriteBool( 'VISTAPREVIA', VISTAPREVIA.Checked );
Reg.WriteDate( 'FECHA', FECHA.Date );
Reg.WriteTime( 'HORA', StrToTime( HORA.Text ) );
Reg.WriteFloat( 'MARGEN', MARGEN.Value );
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;

Para probar si se ha guardado la información pulsa el botón INICIO y opción EJECUTAR: REGEDIT. Las opciones se habrán guardado en la carpeta:

\HKEY_LOCAL_MACHINE\SOFTWARE\MiPrograma


CARGANDO OPCIONES DESDE EL REGISTRO DEL SISTEMA

Antes de cargar las opciones comprueba si existe la clave:

procedure TFPrincipal.CargarRegistroSistema;
var Reg: TRegistry;
begin
// Creamos un objeto para manejar el registro
Reg := TRegistry.Create;

// Guardamos las opciones
try
Reg.RootKey := HKEY_LOCAL_MACHINE;
if Reg.OpenKey( '\Software\MiPrograma', True ) then
begin
IMPRESORA.Text := Reg.ReadString( 'IMPRESORA' );
COPIAS.Value := Reg.ReadInteger( 'COPIAS' );
VISTAPREVIA.Checked := Reg.ReadBool( 'VISTAPREVIA' );
FECHA.Date := Reg.ReadDate( 'FECHA' );
HORA.Text := TimeToStr( Reg.ReadTime( 'HORA' ) );
MARGEN.Value := Reg.ReadFloat( 'MARGEN' );
Reg.CloseKey;
end;
finally
Reg.Free;
end;
end;

Pruebas realizadas en Delphi 7

Publicidad