• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 198
  • Last Modified:

Record Type will not port from Delphi 4 to Delphi 2005. Record size does not match causing the data to load incorrectly.

I have the following record that was originally created in Delphi 4. I now have Delphi 2005. When I try to load this record header the data is corrupt. When I check the size of the record header it is 60 bytes and should be 57, which it is in Delphi 4. Where did the other 3 bytes come from and how do I fix this so the records load correctly in Delphi 2005?

tVersionHeader=record
    version: String[10];
    Application: String[25];
    Updated: TSystemTime;
    Size: LongInt;
    end;
0
shardt
Asked:
shardt
  • 4
  • 3
  • 2
  • +3
1 Solution
 
Jase-CoderCommented:
try doing:

tVersionHeader=record
    version: String;
    Application: String;
    Updated: TSystemTime;
    Size: LongInt;
    end;
0
 
kretzschmarCommented:
maybe also

tVersionHeader= packed record
    version: String[10];
    Application: String[25];
    Updated: TSystemTime;
    Size: LongInt;
    end;


no d2005 on hand

meikl ;-)
0
 
shardtAuthor Commented:
Thanks, for the quick response. I have to specify string lengths as the data is stored on disk. I also tried the packed record and this did not resolve the problem ether.
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
AmigoJackCommented:
when anything did go wrong i would suspect TSystemTime is in delphi 2005 not that what it used to be in delphi 4. however, you should be able to findout yourself with a couple of tests:

- hold CTRL-key and leftclick on TSystemTime with the mouse. this should open you the declaration of it. do it in d4 and in d2005 and check for differences
- same as above, but check the help files instead. in d4 i think TSystemTime comes down to the win32 api type "SYSTEMTIME", but i have no clue if it something completely else in d2005
- do length() operations on each record member. here is what i expect:

  length(.version) = 11    // 10 characters string + 1 for size
  length(.Application) = 26    // 25 for content, 1 for size
  length(.Updated) = 16    // because SYSTEMTIME has 8 times a WORD member
  length(.Size)  = 4    // longint is 32bit: 32 divided by 8 give 4 bytes.

  //  11 + 26 + 16 + 4 = 57


like i said :) i suspect TSystemTime. therefore i think your record above would work if you would find the declaration on SYSTEMTIME in d4 and copy it to d2005 (of course name it to something else, like "TSystemTime_D4 = record") and use that type instead. hope you got it the same way i tried to write it :P
0
 
kretzschmarCommented:
i guessed more on aligned record-members,
but well, no d2005 on hand, so another type-declaration may possible as amigo describes :-))
0
 
ZhaawZSoftware DeveloperCommented:
keyword "packed" will solve this:

type
  TVersionHeader = packed record
    version     : string[10];
    Application : string[25];
    Updated     : TSystemTime;
    Size        : LongInt;
  end;
0
 
ZhaawZSoftware DeveloperCommented:
ou.. looks like some discussion has started while i was "answering", lol..
sorry, don't know how to solve in d2005
0
 
shardtAuthor Commented:
I have compared both D4 & D2005 TSystemTime records and no difference. I have also checked the length of all the elements and all the length match as stated.

 SizeOf(version) = 11    
 SizeOfApplication) = 26    
 SizeOf(Updated) = 16  
 SizeOf(Size)  = 4  

However if you do a SizeOf(TVersionHeader) you get 60 in D2005 and 57 in D4.
0
 
ZhaawZSoftware DeveloperCommented:
"I also tried the packed record" <-- and what about alternatives of keyword "packed"? Is there any in D2005?
0
 
AmigoJackCommented:
maybe also some newer "code optimization" which is turned on in d2005? check project options and turn off anything suspicious
0
 
shardtAuthor Commented:
I am unsure what has changed but got the total record size now to 57 as it should be, however the size element is still not being read correctly. It should be 337 and the value that is being read is nowhare near this. I have looked through the compiler setting and it all matches as to what I have setup in D4. I also rechecked the TSystemTime structure and they also match. I tryed using the packed record and it had no effect.
0
 
pibaCommented:
I have got Delphi 7 and just checked
TVersionHeader=packed record == 57 Byte
TVersionHeader=record == 60 Byte

this record is 60 byte with and without the reserved word packed
type
  TVersionHeader = record
    version     : string[11]; //11+1 mod 4 = 0
    Application : string[27];//27+1 mod 4 = 0
    Updated     : TSystemTime;
    Size        : LongInt;
  end;

Using packed slows data access.
Memory manager blocks are always rounded upward to a 4-byte boundary. which guarantees optimal CPU performance when addressing the block.
(unless explicitly specified otherwise)
0
 
shardtAuthor Commented:
Here is the problem, I need to be able to read the current db on disk. The db header currently on disk is 57. What is the best way to resolve this problem without blowing up the current db and starting from scratch? Using packed record did not help in reading the data correctly off of the disk.
0
 
pibaCommented:
What is the structure of your DB ?

If it is like what stands below then you could try my ButtonReadDBClick procedure

TVersionHeader of 57 byte
then data of a size which varies but its length is in TVersionHeader.size
TVersionHeader of 57 byte
some data
TVersionHeader of 57 byte
some data

procedure TForm1.ButtonReadDBClick(Sender: TObject);type
  TVersionHeader = packed record
    version     : string[10];
    Application : string[25];
    Updated     : TSystemTime;
    Size        : LongInt;
  end;
Const DBFile='test.db';
Const MyRecordSize = sizeof(TVersionHeader);
Var
  MyRecord:TVersionHeader;
  FS:TFileStream;
  ReadRecordNr:Integer;
  ReadRecordPos:Integer;
begin
  FS:=TFileStream.create(DBFile,fmOpenRead);

  ReadRecordNr:=2;

  ReadRecordPos:=0;
  While ReadRecordNr >= 1 Do
  Begin
    FS.Seek(ReadRecordPos,soFromBeginning);
    FS.Read(MyRecord,MyRecordSize);
    Inc(ReadRecordPos,MyRecord.Size);
    Inc(ReadRecordPos,MyRecordSize);
    Dec(ReadRecordNr);
  End;
  ShowMessage(MyRecord.Application+' '+MyRecord.version+
    ' Size:'+IntToStr(MyRecord.Size)+' Year:'+IntToStr(MyRecord.Updated.wYear)
  );
  FreeAndNil(FS);
end;
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 3
  • 2
  • +3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now