Mamx estuve examinando tu propuesta. Le faltaría pulir algunos detalles menores, pero puede que vaya bien encaminada.
Mi duda es ahora, si en el Create del TFileStream hay una excepción teóricamente con el uso del finally no hay forma de detectar que el archivo ha sido leído realmente.
Es más no tiene lugar siquiera el ReadMatrix que propones y no se realiza nada. Tal excepción pasa desapercibida, puesto que es una acción automática que realiza el compilador. Cuand hay una excepción en un constructor se suspende tal reserva de memoria y tiene lugar una liberación de los recursos que si hayan tenido lugar. El método LoadMatrix que propones no dejará a la matrix cargada con los datos del archivo, obviamente, pero no hay tal aviso.
Ese es el punto central. TFileStream es un caso particular en donde las reglas de juego no son tan genéricas. Normalmente no es de esperar un error en un constructor, pero el TFileStream explícitamente fue diseñado para arrojarlas si no ha sido posible crear o cargar el archivo y como tal hay que dar aviso de ello.
Mira esto:
Código Delphi
[-]
constructor TFileStream.Create(const AFileName: string; Mode: Word);
begin
Create(AFileName,Mode,438);
end;
constructor TFileStream.Create(const AFileName: string; Mode: Word; Rights: Cardinal);
begin
FFileName:=AFileName;
If (Mode and fmCreate) > 0 then
FHandle:=FileCreate(AFileName,Mode,Rights)
else
FHAndle:=FileOpen(AFileName,Mode);
If (THandle(FHandle)=feInvalidHandle) then
If Mode=fmcreate then
raise EFCreateError.createfmt(SFCreateError,[AFileName])
else
raise EFOpenError.Createfmt(SFOpenError,[AFilename]);
end;
Y no sólo así son las cosas, que hasta los ReadBuffer y el WriteBuffer den excepción:
Código Delphi
[-]
procedure TStream.ReadBuffer(var Buffer; Count: Longint);
Var
r,t : longint;
begin
t:=0;
repeat
r:=Read(PByte(@Buffer)[t],Count);
inc(t,r);
until (t=Count) or (r=0);
if (tthen
Raise EReadError.Create(SReadError);
end;
procedure TStream.WriteBuffer(const Buffer; Count: Longint);
var
r,t : Longint;
begin
T:=0;
Repeat
r:=Write(PByte(@Buffer)[t],Count);
inc(t,r);
Until (t=count) or (r=0);
if (tthen
Raise EWriteError.Create(SWriteError);
end;
Se que tu propuesta es mucho más limpia, y va muy bien encaminada. Nomás me pregunto sobre la posibilidades de como debiera de tratarse esta clase tan particular.
Saludos,