2008. november 26., szerda
How to store records to a stream for later retrieval
Problem/Question/Abstract:
How to store records to a stream for later retrieval
Answer:
Stores a record to stream. Record can later be retrieved with RecordFromStream procedure.
procedure RecordToStream
(DSet: TDataSet; {Dataset in question}
Stream: TStream; {Stream to store to}
PhysFieldsOnly: Boolean; {Do not store lookup and calculated fields}
FieldsNotStore: array of TField); {Additional fields that should not be stored}
function DoStoreFld(aFld: TField): Boolean;
{Checks whether the field should be stored}
var
i: Integer;
begin
Result := not PhysFieldsOnly or (aFld.FieldNo > 0);
{FieldNo of Lookup and calculated fields is <= 0}
if Result then
for i := 0 to High(FieldsNotStore) do
if aFld = FieldsNotStore[i] then
begin
Result := false;
break;
end;
end;
procedure WriteFldname(fldname: string);
var
L: longint;
begin
L := length(fldname);
Stream.Write(L, sizeOf(L));
Stream.Write(fldname[1], L);
end;
var
I, Cnt, Len: Longint;
Fld: TField;
FldBuff: Pointer;
BStream: TBlobStream;
begin
Cnt := DSet.FieldCount;
Getmem(FldBuff, 256);
try
for i := 1 to Cnt do
begin
Fld := DSet.Fields[i - 1];
if not DoStoreFld(Fld) then
Continue;
WriteFldname(Fld.Fieldname);
if Fld is TBlobField then
begin
BStream := TBlobStream.Create(Fld as TBlobField, bmRead);
try
Len := BStream.Size;
Stream.Write(len, SizeOf(Len));
Stream.CopyFrom(BStream, Len);
finally
BStream.Free;
end;
end
else
begin
Len := Fld.dataSize;
Fld.Getdata(FldBuff);
Stream.Write(Len, SizeOf(Len));
Stream.Write(FldBuff^, Len);
end;
end;
Len := 0;
{Mark the end of the stream with zero}
Stream.Write(Len, SizeOf(Len));
finally
Freemem(FldBuff, 256);
end;
end;
Reads record from the stream. The record was previously stored with RecordToStream procedure. Dset must be in edit/insert mode.
procedure RecordFromStream
(DSet: TDataSet; {Dataset in question}
Stream: TStream; {Stream to retrieve from}
FieldsToIgnore: array of TField); {Fields that should not be retrieved}
function DoReadFld(aFld: tField): Boolean;
var
i: Integer;
begin
Result := (aFld <> nil) and (aFld.FieldNo > 0);
{calculated and lookup fields are allways ignored}
if Result then
for i := 0 to High(FieldsToIgnore) do
if aFld = FieldsToIgnore[i] then
begin
Result := false;
break;
end;
end;
function ReadFldname: string;
var
L: longint;
begin
Stream.Read(L, sizeOf(L));
if L = 0 then
result := ''
else
begin
SetLength(Result, L);
Stream.Read(Result[1], L);
end;
end;
var
Len: Longint;
Fld: TField;
Fldname: string;
FldBuff: Pointer;
begin
Getmem(FldBuff, 256);
try
Fldname := ReadFldname;
while Fldname <> '' do
begin
if Fldname = '' then
break;
Fld := DSet.FindField(Fldname);
Stream.Read(Len, SizeOf(Len));
if DoReadFld(Fld) then
begin
if Fld is TBlobField then
begin
with TBlobStream.Create(Fld as TBlobField, bmWrite) do
try
CopyFrom(Stream, Len);
finally
Free;
end;
end
else
begin
if Fld.datasize <> Len then
raise Exception.CreateFmt('Field size changed: Field: %s', [Fldname]);
Stream.Read(FldBuff^, Fld.dataSize);
Fld.Setdata(FldBuff);
end;
end
else
begin
Stream.Seek(Len, soFromCurrent);
end;
Fldname := ReadFldname;
end
finally
Freemem(FldBuff, 256);
end;
end;
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése