Este tema me hizo recordar la manera en que DBase guardaba la información en lo que ahora conocemos como archivos planos de tablas.
Si revisamos la estructura de un archivo de dbase (
buscando por google aparecen muchos resultados) esta es la idea básica que se puede extraer:
Estructuramos nuestro archivo de tal manera que contenga la definción de los campos que forman la tabla así como los mismos datos.
Tomando como base la estructura que se utilizaba en dbase propongo algo como esto:
Un encabezado que contenga información acerca de cuántos campos tiene nuestra tabla, qué tipo de datos tiene y cuántos registros forman el archivo.
El siguiente espacio lo utilizamos para guardar los datos en bloques de tamaño fijo y al final un delimitador constante para indicar el final del archivo.
La estructura puede ser algo como esto aunque se puede adaptar a las necesidades de cada uno.
Estructura del encabezado
[table]
[tr]
[td]
Tamaño en bytes[/td]
[td]
Descripción[/td]
[td]
Abreviatura[/td]
[/tr]
[tr]
[td]2[/td]
[td]Número de bytes en el encabezado[/td]
[td]
nbe[/td]
[/tr]
[tr]
[td]4[/td]
[td]Número de registros contenidos en el archivo[/td]
[td]
nreg[/td]
[/tr]
[tr]
[td]4[/td]
[td]Número de campos[/td]
[td]
nc[/td]
[/tr]
[tr]
[td]4[/td]
[td]Número de bytes por registro[/td]
[td]
nbr[/td]
[/tr]
[tr]
[td]15*nc[/td]
[td]Arreglo con la descripción de los registros (la estructura de este cada entrada de este arreglo se muestra abajo)[/td]
[td][/td]
[/tr]
[/table]
Estructura de cada uno de los campos
[table]
[tr]
[td]
Tamaño en bytes[/td]
[td]
Descripción[/td]
[/tr]
[tr]
[td]12[/td]
[td]Nombre del campo[/td]
[/tr]
[tr]
[td]1[/td]
[td]Tipo de dato. Los siguientes valores son permitidos:
T =Texto, F = Fecha, E = Entero, N = Numérico
[/td]
[/tr]
[tr]
[td]1[/td]
[td]Longitud del campo[/td]
[/tr]
[tr]
[td]1[/td]
[td]Número de decimales ( solamente tiene sentido cuando el tipo de datos es numérico)[/td]
[/tr]
[/table]
Para que se comprenda mejor la idea esta es la estructura que tendría el archivo:
Estoy proponiendo que los campos sean de cuatro tipos de datos diferentes para hacerlo sencillo. Los tipos de datos se denotan por un caracter que puede ser 'T','F','E','N' para texto, fecha, entero y numérico respectivamente.
En Dbase al eliminar un registro en realidad solamente se marcaba de una manera especial dentro del archivo. Esto se hacía porque eliminar físicamente un registro implicaba muchas operaciones de lectura y escritura en disco que eran lentas en esa época. La manera de solucionarlo fue colocando un byte como marca al principio de cada registro. Si esta marca corresponde al caracter (20h) ASCII que es un espacio en blanco, entoces el registro se considera activo. Si la marca corresponde al caracter (2Ah) ASCII que es un asterisco, entonces el registro se considera inactivo o eliminado. Al final si el archivo crecía demasiado con una operación llamada PACK se eliminaban fisicamente los registros marcados como inactivos en una sola operación.
Ahora viene el trabajo pesado que consiste en crear las rutinas para leer y escribir en este archivo
Lo primero es definir la estructuras necesarias:
TEncabezado = record
nbe: Word; // bytes en el encabezado
nreg: LongWord; // registros en el archivo
nc: LongWord; // número de campos
nbr: LongWord; // bytes por cada registro
end;
TDefCampo = record
Nombre : String[12];
TipoDato : Char; // T =Texto, F = Fecha, E = Entero, N = Numerico
Longitud : Byte;
Decimales: Byte;
end;
PArrayCampos = ^TArrayCampos;
TArrayCampos = array of TDefCampo;
Ahora lo que sigue es crear rutinas para crear la estructura del archivo.
Primero se debe crear una función que permita crear nuevos campos
procedure NuevoCampo(ArrayCampos:PArrayCampos; ANombre:String;ATipoDato:Char;ALongitud,ADecimales: Byte);
var
Dim: Integer;
begin
Dim:=Length(ArrayCampos^);//Obtenemos el tamaño actual del arreglo
Inc(Dim);//Para incrementar el tamaño del arreglo
SetLength(ArrayCampos^,Dim);
//Guardamos la definición del nuevo campo
ArrayCampos^[Dim-1].Nombre:=Copy(ANombre,1,12);//Restringimos la cadena a 12 caracteres
ArrayCampos^[Dim-1].TipoDato:=ATipoDato;
ArrayCampos^[Dim-1].Longitud:=ALongitud;
ArrayCampos^[Dim-1].Decimales:=ADecimales;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
P: PArrayCampos;
NC: Integer;
I: Integer;
begin
//Creamos un arreglo y agregamos dos campos
New(P);
NuevoCampo(P,'Nombre','T',20,0);
NuevoCampo(P,'Apellidos','T',40,0);
//Para probar que funciona
NC:=Length(P^); //Obtenemos el total de campos
ShowMessageFmt('%d',[ NC]);
for I := 0 to Dim - 1 do
ShowMessage(P^[I].Nombre);
Dispose(P);
end;
Con esto tenemos lo necesario para crear múltiples campos en nuestra tabla.
Ahora tenemos que hacer una rutina para guardar registros en estos campos, también faltan las rutinas para guardar todo en el archivo y después recuperarlo.
Por le momento no puedo continuar con el ejercicio, pero esto da una idea general de lo que propongo para resolverlo.
Espero que sea útil
Saludos