Link to home
Start Free TrialLog in
Avatar of seabear
seabear

asked on

Delphi 5 problem with typed file - OK in Delphi 4

I have a program which saves and reads information using a typed file
It works without problems in Delphi 4 but in Delphi 5 it compiles and runs but seems to read the file wrongly.

The record type is
    THoliday = record
        name : string[40];
        dateBegins : TDateTime;
        dateEnds : TDateTime;
    end;

The code which fails is shown below and the point at which it crashes is given by the comment in the middle. The first few bytes in the first record, the name, are Ok but the dates are garbage:
procedure TfrmClassDates.FormCreate(Sender: TObject);
var
   HolData :THoliday;
   strName : string[42];
   strBegin : string[10];
   strEnd : string[10];
   strLine : string;
begin
   HolidayFileName := 'TheHOLS.BIN';
   AssignFile(HolidayFile, HolidayFileName);
   if FileExists(HolidayFileName) then
       begin
       Reset(HolidayFile); //open existing file
       HolCount := 0;
       isSaved := true;
       while not Eof(HolidayFile) do
           begin
           Read(HolidayFile, HolData);
           HolCount := HolCount + 1;
           HolArray[HolCount] := HolData;
           strName := HolData.name;
           strBegin := DateToStr(HolData.dateBegins);  

           // Program crashes at the line above
           // or the next line below with invalid floating point operation
           // only if compiled under Delphi 5 works fine with Delphi 4
           // debugger shows dateBegin values are garbage

           strEnd := DateToStr(HolData.dateEnds);
           strLine := format('%-14s %9s %9s',[strName,strBegin,strEnd]);
           lstHolidays.items.add(strLine);
           end;
       CloseFile(HolidayFile);
       dtpStartDate.DateTime := HolArray[1].dateEnds + 1;
       end
   else
       begin
       ShowMessage('Could not find the standard holiday file "theHols.bin"'
                     + #13#10 + ' in "H:\...\tutors\schedule"');
       end;
end;
Avatar of simonet
simonet
Flag of Brazil image

Try this:

    THoliday = packed record
        name : string[40];
        dateBegins : TDateTime;
        dateEnds : TDateTime;
    end;

Yours,

Alex
You may also want to use ShortString instead of String on the TYPE definition.

Alex
Avatar of seabear
seabear

ASKER

Hi Alex
packed does not fix the problem, also I am dealing with existing files created without the packed clause.

How would I use shortstring to get a fixed string length of 40 bytes?
    name : shortstring[40];
gives a complier error "; expected [ found"

Dan
Hi seabear,

I've written some delphi-programs who use text-files.
Those textfiles are of the Line-Sequential Type
(1 line = 1 record, each line is terminated with CR/LF).

What I do to access these files is the following :

1) Create a SCHEMA-File (= NameTextFile.SCH)
   This is a file who contains the record-description.
   This file is located in the same directory as your textfile +
   it must have the same name + extension SCH.
   The advantage of working with schema-files is that you can access
   textfiles like tables (without edit or delete functionality).
   For your file :
         [HOLIDAYS]
      FileType=FIXED
      Delimiter=
      Separator=
      CharSet=ascii
      Field1=Name,CHAR,40,0,0
      Field2=DateBegins,CHAR,10,0,40
      Field3=DateEnds,CHAR,10,0,50

2) In your application, you drop a table-component on your Form.
   2 properties must be set :
     A) TableType must be set to ASCII.
     B) TableName must be set to the location + name of the textfile.


3) Now on the FormCreate Event, you can put the following code to fill
   the contents of your ListBox :
      procedure TForm1.FormCreate(Sender: TObject);
      var
        strName  : String;
          strBegin : String;
          strEnd       : String;
          strLine       : String;
      begin
        With Table1 do
        begin
          Active := True; { Open Table (= TextFile) }
            First; {Goto first record }
            While not eof do
            begin
              strName  := FieldByName('Name').AsString;
              strBegin := FieldByName('DateBegins').AsString;
              strEnd   := FieldByName('DateEnds').AsString;
              strLine  := Format('%-14s %9s %9s',[strNAme,strBegin,strEnd]);
              ListBox1.Items.Add(strLine);
              Next; { Goto next record }
            end;
            Active := False; { Close Table (= TextFile) }
          end;
        end;


Maybe you can try this.
Hope it works.


Best regards,
The M@yor.
ASKER CERTIFIED SOLUTION
Avatar of kretzschmar
kretzschmar
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Try changing your record structure to this:

    THoliday = packed record
        name : string[40];
        Dummy : array[1..3] of byte// Suck up three bytes
        dateBegins : TDateTime;
        dateEnds : TDateTime;
    end;

Its a bit weird really, D5 appears to be padding two bytes after the two date fields, and I can't see way it should!

Cheers,

Raymond;
hi raymond,
same idea ;-)
Avatar of seabear

ASKER

Thanks wimmeyvaert but I wanted a simple fix to allow me to read and edit exiting files created with D4. Your technique looks interesting though.



Note to Meikl and Raymond yep you've got it. This works fine

I shall reject the proposed answer then accept Meikl's comment as the answer since he got in first. (By one minute!!!!) Thanks to you both. If one of you has time could you tell me why this works? Why packed in D5 and not D4 and why the extra 3 bytes? Anyway thanks again - Dan
hi dan,

first glad that this solves your problem,

well i try to explain,
in both delphi versions is the packed record-size of your original-recordstructure the same (57 Bytes).

as you coded in d4 you didn't use the keyword packed in the record-definition, therefore the compiler has aligned the recordstructure to 32Bit alignment for better performance by addressing the fields in the structure.

by doing this, the compiler left three bytes 'blank' between your string and the dates. the recordsize becomes 60 Bytes.

why in d5 now, additional 2 bytes are appended by the datefields, i don't know it, its against the alignment-philosophy, except the addressbus will become wider in near future.

well the idea from us both was, in d5 this alignment from d4 to do by hand, by avoiding the alignment with the keyword packed in the record-definition, and inserting 3 bytes after the string.

hope this explaination helps a little

meikl ;-)
Avatar of seabear

ASKER

Thanks Meikl that clears it up for me - Dan