PDA

View Full Version : Data files



Ixy
31-05-2009, 08:57 AM
It's been bugging me for some time, but it's a pretty basic problem really.

e.g.
type students = record
....
....
file1 = file of student

var student: students;
dat: file1;
....


As you can see here, I have a data file that is a file of a record.
My problem is - I have a procedure for adding students and it works fine. But the program needs to have a procedure (it doesn't HAVE to be a procedure) in which you change their data (e.g. address, phone number etc.) and I'm just stuck.

Can you even change stuff once it's all written in the file? How?
If not, how should I get around the problem? :(

Thanks!

Brainer
31-05-2009, 09:25 AM
It's simple. :) First of all, you're using fixed-size records, so that you can easily seek in your file. I'd suggest you using streams. So to write anything, you use:


type
TRecord = record
MyInteger: Integer;
MySingle: Single;
MyString: ShortString;
end;

procedure WriteFile;
var
FS: TFileStream;
Rec: TRecord;
begin
FS := TFileStream.Create('C:\myfile.dat', fmCreate);
try
Rec.MyInteger := 10;
Rec.MySingle := 3.14;
Rec.MyString := 'Simple string';

FS.Write(Rec, SizeOf(TRecord));
finally
FS.Free();
end;
end;


Now, to modify a record:

procedure ModifyRecord(const ARecordIdx: Cardinal; const ARecord: TRecord);
var
FS; TFileStream;
begin
FS := TFileStream.Create('C:\myfile.dat', fmOpenReadWrite + fmShareExclusive);
try
FS.Seek(ARecordIdx * SizeOf(TRecord), soFromBeginning);
FS.Write(ARecord, SizeOf(TRecord));
finally
FS.Free();
end;
end;


I hope it's clear now. :)

AthenaOfDelphi
31-05-2009, 10:59 AM
Brainer's solution will work, if you are using streams... but you're using standard Pascal file handling from what I can see, so this is how you do it...

When you create the file, you open it with 'rewrite'. This creates the file everytime. When you want to edit a record or just read the data in the file, you open the file with 'reset' and then use 'seek' to find the record you want based on it's record number.

There are other routines which you may find useful... 'filepos' returns the current record number, 'filesize' returns the total number of records in the file. Record indices start at 0 for the first record.

When you want to edit a record, you use 'seek' to get to the record you want to edit, then read it using 'read'. Make the changes to the record in memory, then move back to it (remember 'read' advances the files record pointer) using 'seek' and then simply 'write' the record back.

So, the first time you open the file use 'rewrite' to create it. The next time, check if it exists using 'fileexists' and if it does, open it with 'reset'. If you want to add a new record, remember to go to the end of the file using something like 'seek(f,filesize(f))'.

These are the standard file handling commands for real Pascal files... there are others but these are for specific file types ('append' for example is only for use with text files).

Ixy
31-05-2009, 08:54 PM
Doh, I worked it out. :D
Thanks.

But now I have a different problem.
I'm using crt and gotoxy to format the view better.
My question is - can I somehow define the size of the window in which the program opens?

When I run it on my computer, it looks fine, but when my friend runs it on his computer, the screen is smaller, so everything kind of scrambles... :(

EDIT:
Solved that through windows. ;)

arthurprs
01-06-2009, 12:57 AM
EDIT:
Solved that through windows. ;)


how ? I had this problem on the past but i wasn't able to solve it =\

Ixy
01-06-2009, 04:52 PM
Well, you open the exe file and it runs in a pretty small window (at least in win xp). Then right click on the border of the window -> properties -> layout. And change the settings there. ;)

Now I have a new problem. For some reason, everytime i want to write something to a file, I get exitcode 5.
Which is "File access denied." :(

Wizard
01-06-2009, 06:04 PM
Don't know if this will help - exit code 5 is a file I/O access error, try and change the filemode :)

arthurprs
02-06-2009, 01:08 AM
Well, you open the exe file and it runs in a pretty small window (at least in win xp). Then right click on the border of the window -> properties -> layout. And change the settings there. ;)

Now I have a new problem. For some reason, everytime i want to write something to a file, I get exitcode 5.
Which is "File access denied." :(


uhm, but how about changing the console size in the program?

User137
02-06-2009, 08:25 AM
uhm, but how about changing the console size in the program?

Is it same console than OS opens when you start command prompt? In that case above instruction would make sense.

User137
02-06-2009, 08:35 AM
Now I have a new problem. For some reason, everytime i want to write something to a file, I get exitcode 5.
Which is "File access denied." :(
Maybe something useful here:
http://www.delphibasics.co.uk/RTL.asp?Name=Reset
"Reset - Open a text file for reading, or binary file for read/write"

Make sure you use Write, not Writeln? If doesn't work we might need to see the use of these commands in your program.

Also "myFile : TextFile;" < this is not allowed as you need a binary file.
http://www.delphibasics.co.uk/RTL.asp?Name=Write

I have actually never tried using dynamic block sizes with this method. Is it possible?

AthenaOfDelphi
02-06-2009, 11:07 AM
RE: Dynamic block sizes...

In traditional file handling using Pascal, no, dynamic block sizes aren't allowed. You have to know exactly the length of the data you are going to store. This obviously precludes the use of long strings. So every string in the records should be of the form string[ x ] (x is in the range 1 to 255). There are of course other things you can't store... dynamic arrays for example.

noeska
02-06-2009, 05:42 PM
why are you doing things the 'old' way. I would suggest to look into streams as suggested by Brainer.

Also have a read on
http://delphi.about.com/od/fileio/a/fileof_delphi.htm (your 'old' way)
and
http://delphi.about.com/od/vclusing/l/aa110803a.htm (streams the 'new' way)

AthenaOfDelphi
02-06-2009, 07:10 PM
I don't want to get drawn into an argument about which method is best because quite simply the choice of which mechanism you use will be (or more accurately, should be) governed by what you are using it for.

Streams have their plus sides, namely the ability to stream across different mediums and the relative ease with which they can cope with variable sized records (NOTE: I said relative ease... some things that are a breeze with standard file handling can become a real nightmare with a stream based mechanism).

Traditional files are simple to use... define the record type, declare a file variable and you're half way there. They can be a pain in the ass when you want to add or remove data from the records you've stored... but then so too can streams.

I would recommend learning about standard file handling first... you don't have to concern yourself with all the technicalities of the streaming mechanisms (like calculating record byte offsets).

Ixy:- if you are still having problems with the filehandling, then post your code. Without seeing it, it's hard to know whats going on so we can only guess at possible solutions.

Ixy
02-06-2009, 10:32 PM
No, I solved my problem. ;)

But NOW I have the craziest problem ever.
The program doesn't want to run under XP anymore.
On my Windows 7 beta it runs fine, but on XP... it just opens and closes fast...

What the hell?

EDIT:
:D

Found the problem. I changed the path for testing purposes and forgot to change it back. :D