?
Solved

Delphi 5 problem with typed file - OK in Delphi 4

Posted on 1999-11-23
10
Medium Priority
?
203 Views
Last Modified: 2010-04-04
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;
0
Comment
Question by:seabear
  • 3
  • 3
  • 2
  • +2
10 Comments
 
LVL 15

Expert Comment

by:simonet
ID: 2230091
Try this:

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

Yours,

Alex
0
 
LVL 15

Expert Comment

by:simonet
ID: 2230093
You may also want to use ShortString instead of String on the TYPE definition.

Alex
0
 

Author Comment

by:seabear
ID: 2230193
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
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 6

Expert Comment

by:wimmeyvaert
ID: 2230533
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.
0
 
LVL 27

Accepted Solution

by:
kretzschmar earned 300 total points
ID: 2230577
hi seabear,

i see your problem
your record has a
packed size of 57 Bytes

in d4 the record will aligned to 60 Bytes

in d5  the record will aligned to 64 Bytes

i guess your records are created with a d4 app, and you will now access the records with d5

maybe a recordstructure like this helps

    THoliday = packed record  //no align
        name : string[40];
        Filler : String[2];   //fill three bytes
        dateBegins : TDateTime;
        dateEnds : TDateTime;
    end;


just not tested, but in d5 the record now have also 60 Bytes, maybe the filler is on the wrong place

meikl
0
 
LVL 12

Expert Comment

by:rwilson032697
ID: 2230580
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;
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2230626
hi raymond,
same idea ;-)
0
 

Author Comment

by:seabear
ID: 2232792
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
0
 
LVL 27

Expert Comment

by:kretzschmar
ID: 2232845
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 ;-)
0
 

Author Comment

by:seabear
ID: 2233079
Thanks Meikl that clears it up for me - Dan
0

Featured Post

[Webinar] Kill tickets & tabs using PowerShell

Are you tired of cycling through the same browser tabs everyday to close the same repetitive tickets? In this webinar JumpCloud will show how you can leverage RESTful APIs to build your own PowerShell modules to kill tickets & tabs using the PowerShell command Invoke-RestMethod.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
How to fix display issue, screen flickering issue when I plug in power cord to the machine. Before I start explaining the solution lets check out once the issue how it looks like after I connect the power cord. most of you also have faced this…
SQL Database Recovery Software repairs the MDF & NDF Files, corrupted due to hardware related issues or software related errors. Provides preview of recovered database objects and allows saving in either MSSQL, CSV, HTML or XLS format. Ensures recov…
Suggested Courses

588 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question