2
« en: Miércoles 15 de Mayo de 2013, 16:06 »
Hola chicos/as como andan?
Queria consultarles si tienen algun recurso, que explique lo mejor posible el manejo de archivos con registros de longitud variable, y con el manejo de bloques.
Ya que tengo un libro pero la verdad que no explica demasiado bien. Y los ayudantes en la materia son un desastre.
por ahora lo que entiendo, es que no se utiliza una estructura (no se declaran los tipos) como en los de longitud fija, si no que se utilizan bloques de x tamaño de byte, donde cada campo se delimita por un caracter x y cada registro por un caracter y, les dejo el codigo de un ejemplo, o un intento de explicacion de la cursada, lo cual no entiendo para que joden tanto en materias anteriores con la legibilidad del codigo y la correcta indentacion si estos son un desastre :S
{Manejo de archivo secuencial de personas, con registros de longitud variable.
Los comentarios y salidas en pantalla se escriben sin acentos para se vean
siempre igual en todo entorno.
Autor: Arturo Servetto}
Interface
Const
TamBloque = 64;
CapacBloque = TamBloque-SizeOf(Word);
PorcCarga = 0.9; {Porcentaje de carga de los bloques (se deja espacio
disponible por si se actualizan registros aumentando su longitud, para no
tener que cambiarlos de bloque)}
PersonaFin = 'fin'; {para representar el fin del archivo}
Type
tNombre = String[31]; {para manejar personas en memoria}
tBloque = Record
cantRegs: Word; {cantidad actual de registros en el bloque}
contenido: Array[1..CapacBloque] of Byte
end;
Modo = (esc, lecOesc); {modo de apertura del archivo: esc(ritura), o
lec(tura)Oesc(ritura)}
tPersonas = Record
arch: File of tBloque; {archivo de personas}
espLibre: File of Word; {archivo de control de bytes libres por
bloque del archivo de personas}
m: Modo; {modo en que esta abierto el archivo}
bloque: tBloque; {ultimo bloque leido de personas}
iBloque: Word; {indice de posicion dentro del bloque}
espLibreBloque: Word
end;
Procedure Abrir(var pp: tPersonas);
Procedure Cerrar(var pp: tPersonas);
Procedure Crear(var pp: tPersonas);
Procedure Cargar(var pp: tPersonas; p: tNombre); {alta secuencial}
Procedure Agregar(var pp: tPersonas; p: tNombre); {alta con busqueda de espacio}
{Dada la simplicidad del problema, no se verifica la unicidad de los nombres}
Procedure Primero(var pp: tPersonas; var p: tNombre); {primer registro del
archivo}
Procedure Siguiente(var pp: tPersonas; var p: tNombre; var inicio: Boolean);
{recuperacion secuencial - inicio True implica primer registro del bloque}
Procedure InfoBloque(var pp: tPersonas; var info: String);
Procedure Obtener(var pp: tPersonas; pb: tNombre; var result: Boolean);
{Se busca pb en el archivo con resultado True si se encuentra}
Procedure Eliminar(var pp: tPersonas; p: tNombre; var result: Boolean);
{result falso implica que no se encuentra la persona}
Procedure Modificar(var pp: tPersonas; pb: tNombre; var p: tNombre;
var result: Boolean);
{result falso implica que no se encuentra la persona}
(******************************************************************************)
Implementation
Procedure Abrir(var pp: tPersonas);
Begin
With pp do begin Reset(arch); Reset(espLibre); m:=lecOesc end
end;
Procedure Cerrar(var pp: tPersonas);
Begin
With pp do begin
If m=esc {si el archivo se abrio para cargarlo}
then If pp.bloque.cantRegs>0 {si el ult. bloque tiene contenido no grabado}
then With pp do begin {se escribe el ultimo bloque}
Write(arch, bloque); Write(espLibre, espLibreBloque)
end;
Close(arch); Close(espLibre)
end
end;
Procedure Crear(var pp: tPersonas);
{Inicializa la estructura y crea los archivos. Los archivos deben estar
asignados}
Begin
With pp do begin
Rewrite(arch); Rewrite(espLibre); m:=esc;
bloque.cantRegs:=0;
iBloque:=1;
espLibreBloque:=CapacBloque
end
end;
Procedure Cargar(var pp: tPersonas; p: tNombre);
{Agrega una persona en el bloque actual o comienza un nuevo bloque al final del
archivo (no se busca espacio libre). El bloque actual es el ultimo del archivo}
Var
tamReg: Byte;
disponibles: Integer; {bytes disponibles en un bloque, sin exceder el porc.
de carga}
Begin
tamReg:=Length(p)+1; {longitud del nombre mas un byte por el prefijo de longitud}
disponibles:=pp.espLibreBloque-Round((1-PorcCarga)*CapacBloque);
If tamReg>disponibles
then {el registro sobrecarga al bloque actual}
With pp do begin
Write(arch, bloque); Write(espLibre, espLibreBloque);
bloque.cantRegs:=0; espLibreBloque:=CapacBloque;
iBloque:=1;
end;
With pp do begin {se agrega el registro al bloque actual}
Move(p, bloque.contenido[iBloque], tamReg); {movemos de una direccion de memoria a otra direccion de memoria}
Inc(iBloque, tamReg);
Inc(bloque.cantRegs);
Dec(espLibreBloque, tamReg)
end
end;
Procedure Agregar(var pp: tPersonas; p: tNombre);
{Agrega una persona en el primer bloque que tenga espacio o, si no hay ninguno,
en un bloque nuevo al final del archivo}
Var
tamReg: Byte;
libres: Word;
disponibles: Integer;
Begin
With pp do begin
Seek(espLibre, 0);
tamReg:=Length(p)+1;
Repeat
Read(espLibre, libres);
disponibles:=libres-Round((1-PorcCarga)*CapacBloque) {bytes libres menos los que
no se pueden usar para altas}
until eof(espLibre) or (disponibles>=tamReg);
If tamReg>disponibles
then begin {hay que agregar un nuevo bloque al final del archivo}
bloque.cantRegs:=0;
libres:=CapacBloque;
iBloque:=1;
Seek(arch, FileSize(arch))
end
else Begin
Seek(arch, FilePos(espLibre)-1); Read(arch, bloque);
iBloque:=CapacBloque-libres+1;
Seek(arch, FilePos(espLibre)-1); seek(espLibre, FilePos(espLibre)-1)
end;
Move(p, bloque.contenido[iBloque], tamReg);
Inc(bloque.cantRegs);
Dec(libres,tamReg);
Write(arch, bloque); Write(espLibre, libres)
end
end;
Procedure Primero(var pp: tPersonas; var p: tNombre); {inicio de secuencia}
{Devuelve el primer registro de persona. El archivo debe tener al menos una
persona}
Var
tamReg: Byte;
Begin
With pp do begin
Seek(arch, 0); Read(arch, bloque); tamReg:=bloque.contenido[1]+1;
Move(bloque.contenido[1], p, tamReg);
iBloque:=tamReg+1; Seek(espLibre, 0); Read(espLibre, espLibreBloque)
end
end;
Procedure Siguiente(var pp: tPersonas; var p: tNombre; var inicio: Boolean);
{Devuelve la siguiente persona a partir de la ultima devuelta, o PersonaFin si
la ultima devuelta fue la ultima del archivo}
Var
tamReg: Byte;
Begin
With pp do begin
If (iBloque>CapacBloque-espLibreBloque) and (not eof(arch))
then begin {no hay más registros en el bloque}
Read(arch, bloque); iBloque:=1; Read(espLibre, espLibreBloque);
inicio:=True
end
else inicio:=False;
If iBloque<CapacBloque-espLibreBloque
then begin
tamReg:=bloque.contenido[iBloque]+1;
Move(bloque.contenido[iBloque], p, tamReg);
Inc(iBloque, tamReg)
end
else p:=PersonaFin
end
end;
Procedure InfoBloque(var pp: tPersonas; var info: String);
Var nb, crr, bbll: String[5]; {numero de bloque, cantidad de registros, bytes
libres}
Begin
Str(FilePos(pp.arch)-1, nb);
Str(pp.bloque.cantRegs, crr);
Str(pp.espLibreBloque, bbll);
info:='Bloque '+nb+': '+crr+' personas - '+bbll+' bytes libres'
end;
Procedure Obtener(var pp: tPersonas; pb: tNombre; var result: Boolean);
{Se busca pb en el archivo con resultado True si se encuentra}
var inicio: Boolean; p: tNombre;
Begin
With pp do begin
Primero(pp, p);
While (p<>PersonaFin) and (p<>pb) do Siguiente(pp, p, inicio);
If p=pb then result:=True else result:=False
end
end;
Procedure Eliminar(var pp: tPersonas; p: tNombre; var result: Boolean);
{result falso implica que no se encuentra la persona}
var resObt: Boolean; resto: Word; tamReg: Byte;
Begin
Obtener(pp, p, resObt);
If resObt
then With pp do begin {se encuentra a la persona}
resto:=CapacBloque-espLibreBloque-iBloque+1;
tamReg:=Length(p)+1;
If resto>0 then
{si no esta al final se corren a izq. las siguientes}
Move(bloque.contenido[iBloque], bloque.contenido[iBloque-tamReg], resto);
Dec(bloque.cantRegs); Inc(espLibreBloque, tamReg);
Seek(arch, FilePos(arch)-1); Write(arch, bloque);
Seek(espLibre, FilePos(espLibre)-1);
Write(espLibre, espLibreBloque);
result:=True
end
else result:=False
end;
Procedure Modificar(var pp: tPersonas; pb: tNombre; var p: tNombre; var result: Boolean);
var resObt: Boolean; resto: Word; tamReg: Byte;
Begin
Obtener(pp, pb, resObt);
If resObt
then with pp do begin
resto:=CapacBloque-espLibreBloque-iBloque+1;
tamReg:=Length(pb)+1;
If resto>0 {si no esta al final se corren a izq. las siguientes}
then Move(bloque.contenido[iBloque],
bloque.contenido[iBloque-tamReg], resto);
Inc(espLibreBloque, tamReg);
iBloque:=CapacBloque-espLibreBloque+1;
tamReg:=Length(p)+1;
If tamReg>espLibreBloque {en este caso no se considera el factor de
carga}
then begin {no entra en el bloque actual; se graba el actual y el
valor modificado se trata como un alta}
Seek(arch, FilePos(arch)-1); Write(arch, bloque);
Seek(espLibre, FilePos(espLibre)-1);
Write(espLibre, espLibreBloque);
Agregar(pp, p)
end
else begin {se agrega el valor modificado al final del bloque}
Move(p, bloque.contenido[iBloque], tamreg);
Dec(espLibreBloque, tamReg);
Seek(arch, FilePos(arch)-1); Write(arch, bloque);
Seek(espLibre, FilePos(espLibre)-1);
Write(espLibre, espLibreBloque)
end;
result:=True
end
else result:=False
end;
Desde ya muchisimas gracias