Reputation: 13
We have a legacy dataset in which one of the fields (the last) was used for saving a packed record.
We need to access this data now and I thought reading it back into a packed record would be pretty simple - but not so much. Seems like I'm striking out.
The folks that designed/wrote the code are long gone so I'm left with what I can discover.
Here's what I have so far -
The packed record format written was:
TRecordStru = packed record
RecData1 : integer ;
RecData2 : array [0..9] of char ;
RecData3 : array [0..9] of char ;
RecData4 : integer ;
RecData5 : array [0..9] of char ;
RecData6 : integer ;
end;
The code to create the packed record was:
with myRecord do // TRecordStru
begin
RecData1 := Num1 ; // integer
StrPLCopy(RecData2,StrData2,sizeof(RecData2)) ; // mm/dd/yyyy
StrPLCopy(RecData3,StrData3,sizeof(RecData3)) ;
RecData4 := Num2 ; // integer
StrPLCopy(RecData5,StrData5,sizeof(RecData5)) ;
RecData6 := Num6 ; // integer
end;
The code which created the data for the field:
...
var
tmpData : string
...
tmpData := spaces(sizeof(myRecord)); // TRecordStru
move(myRecord,tmpData[1],sizeof(myRecord));
...
And the code which saved the data to the field:
...FieldByName('myField').AsString := VarToStr(Value)+#0 ; // variant
For reading it back, I have tried the following:
The DataType
reported by FieldByName('myField').DataType
is ftBytes
.
I am able to get the data into a buffer using:
FieldByName('myField').GetData(myBuffer)
myBuffer
is defined as:
myBuffer : array of byte;
And initialized like this:
getmem(myBuffer,260) ;
I can see the data is there, and could be manually parsed, but is there a 'correct' way of doing this?
Upvotes: 0
Views: 145
Reputation: 265
I would use something like this. Perhaps with additional checks.
type
PRecordStru = ^TRecordStru;
// ...
function RecToVar(const pSource: PRecordStru): Variant;
var
pValue: PByte absolute pSource;
i: Integer;
begin
Result := Null;
if ( nil = pSource ) then exit;
try
Result := VarArrayCreate([0, SizeOf(TRecordStru) - 1], varByte);
except
exit;
end;
for i := 0 to SizeOf(TRecordStru) - 1 do
begin
Result[i] := pValue[i];
end;
end;
function VarToRec(const vSource: Variant; const pTarget: PRecordStru): Boolean;
var
pValue: PByte absolute pTarget;
i: Integer;
begin
Result := ( pTarget <> nil )
and VarIsArray(vSource)
and ( 1 = VarArrayDimCount(vSource) )
and ( SizeOf(TRecordStru) - 1 = VarArrayHighBound(vSource, 1) );
if ( not Result ) then exit;
for i := 0 to SizeOf(TRecordStru) - 1 do
begin
pValue[i] := vSource[i];
end;
end;
procedure TForm1.Button2Click(Sender: TObject);
var
r: TRecordStru;
begin
r.RecData1 := 1;
r.RecData2 := '2222222222';
r.RecData3 := '3333333333';
r.RecData4 := 4;
r.RecData5 := '5555555555';
r.RecData6 := 6;
MyDataSet.Append();
// ...
MyDataSet.FieldValues['myField'] := RecToVar(@r);
MyDataSet.Post();
end;
procedure TForm1.Button3Click(Sender: TObject);
var
r: TRecordStru;
begin
if ( VarToRec(MyDataSet.FieldValues['myField'], @r) ) then
begin
// ...
end;
end;
Upvotes: 0