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.dateBegi ns);
// 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,str End]);
lstHolidays.items.add(strL ine);
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;
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(
var
HolData :THoliday;
strName : string[42];
strBegin : string[10];
strEnd : string[10];
strLine : string;
begin
HolidayFileName := 'TheHOLS.BIN';
AssignFile(HolidayFile, HolidayFileName);
if FileExists(HolidayFileName
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.dateBegi
// 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,str
lstHolidays.items.add(strL
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;
You may also want to use ShortString instead of String on the TYPE definition.
Alex
Alex
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
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').AsStri ng;
strBegin := FieldByName('DateBegins'). AsString;
strEnd := FieldByName('DateEnds').As String;
strLine := Format('%-14s %9s %9s',[strNAme,strBegin,str End]);
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.
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,
Field3=DateEnds,CHAR,10,0,
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').AsStri
strBegin := FieldByName('DateBegins').
strEnd := FieldByName('DateEnds').As
strLine := Format('%-14s %9s %9s',[strNAme,strBegin,str
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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;
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 ;-)
same idea ;-)
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
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 ;-)
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 ;-)
ASKER
Thanks Meikl that clears it up for me - Dan
THoliday = packed record
name : string[40];
dateBegins : TDateTime;
dateEnds : TDateTime;
end;
Yours,
Alex