General
Files provide NON VOLATILE data storage (ie remain when power
off)
There are 2 main classifications of files - Sequential Access
and Random Access.
In order to access a Sequential access file, the file must
be read from the beginning. To find a particular record in a sequential
access file, you must begin your search from the beginning. In the
worst case, the entire file might be searched to discover the
required record is the last one. Clearly if the file is large, this
may be very time consuming. A good analogy is an Audio Cassette -
to find the song you want on a cassette, you start searching from
the beginning of the tape.
Accessing a Random access file is fundamentally different
- each record is indexed, meaning you can access any record you like
instantly. A suitable analogy is an audio CD - you can get to any
song (be it the first or the last) with equal speed of access.
In Pascal, there are 2 main types used - PASCAL DATA FILES (which
are random access), and TEXT FILES (which are sequential access).
PASCAL DATAFILES
As a Random Access File, each part is accessible without reference
to any other part (compared with sequential access files where the
entire file has to be read from the beginning until the part being
searched for is found)
The Operating System views random access files as objects,
it is not interested in file structure, knows its size, type, date
of save, and cluster info (FAT). Can manipulate whole file (copy,
rename, delete...)
Lazarus has no direct knowledge of the total file size or location
on disk, no knowledge of file status. Pascal views a Pascal Data File
as comprising COMPONENTS. Each component is organised due to its type
(any type except file). Only ONE component can be accessed at one
time. Has ability to share intimate knowledge of data structure within
each component.
Pascal datafiles generally
- resides in secondary memory (disk, cartridge, tape)
- ONE component accessible at once
- Pascal allows an 'unlimited' number of components
- Pascal must READ a component from disk or WRITE it back
- Pascal and DOS must cooperate - the file 'belongs' to DOS so Pascal
must 'ask' OS to do work for it.
Because the Operating system (OS) owns the file, different procedures
for establishing a new file (REWRITE) or using an existing file (RESET).
these can't be interchanged --> OS will intervene and may 'crash'
your program.
Setting Up a New Data File In Lazarus
Var HighestScore : integer;
ScoreFile : file of integer;
Begin
HighestScore := 0;
assignfile (ScoreFile,'A:\DATA\HISCORE.DAT');
rewrite(ScoreFile);
write(ScoreFile,HighestScore);
closefile(ScoreFile);
assignfile = Pascal Identifier <---> OS filename link
establishment
rewrite = OPEN a new file, named in assign
write = dump integer 'highestscore' into file (2 bytes) - OS
does this, noting clusters etc in FAT
closefile = OS asked to place an EOF marker and perform file
housekeeping
Using an Existing Pascal Data File
assignfile (ScoreFile,'A:\DATA\HISCORE.DAT');
reset(ScoreFile);
read(ScoreFile,HighestScore);
closefile(ScoreFile);
:
: {the rest of the game}
:
reset(ScoreFile);
write(ScoreFile,HighestScore);
closefile(ScoreFile);
reset = open (if not already open) an existing file and place
file pointer on the first component of the file
write = dump a value, then advance the file pointer to point
at the next component
IT IS A LOGICAL ERROR to rewrite a file that already exists, and
unpredictable damaging results will be the result of such an attempt
Files With Multiple Components
write(destination,value) general form of output statement
...where destination could be lst (printer) or pascal file
name
while not eof(filename)
allows you to continually read from a disk file until the end of file
marker is encountered
successive read/writes advance file pointer to next component after
action.
reset repoints to first component again
Finding a Particular Component
choices : loop sequentially (horribly inefficient and akin to sequential
access) or seek
eg:suppose we want the 16th component from a file, then
assignfile(filename,'a:\DOSNAME.TXT');
reset(filename);
seek(filename,15);
read(filename,Sixteenth_component);
closefile(filename)
NOTE that to point the file pointer at the 16th component, we had
to SEEK number 15 - that is because file contents begin at component
0.
Storing Tables In Files
Suppose we have the following table stored in memory:
Name Rank Sernum
Moncrieff G Lc 362426
Nigglerbater G Gen 42
Parrts O Pt NCC1701
Grable B Lt 386222
with the following definitions:
Type range = 1..20;
soldiers = record
name : string[30];
rank : string[5];
sernum : 0..maxint
end;
Var table : array [range] of soldiers;
soldier, nsold : range;
soldierfile : file of soldiers;
Begin
{input section}
{write a new file}
assignfile(soldierfile,'d:\SOLDIERS.DAT');
rewrite(soldierfile);
for soldier := 1 to nsold do
write(soldierfile,table[soldier]);
closefile(soldierfile);
{get back whole file - unknown # of components}
reset(soldierfile);
soldier :=0;
while not eof(soldierfile) do
begin
read(soldierfile,table[soldier+1]);
inc(soldier)
end;
closefile(soldierfile);
NOTE: If access to individual elements in the saved table is not
required, then the entire table can be saved in a single write statement,
or read with one read:
write(soldierfile,table)
read(soldierfile,table)
Modifying a particular row in a file
To modify existing contents of a data file (so long as each row has
been sequentially saved and assign already done), we could use code
similar to the folowing:
write('Which soldier number? :'); readln(soldier);
reset(soldierfile);
seek(soldierfile,soldier-1); {position file pointer}
read(soldierfile,table[soldier]); {get table row}
with table[soldier] do
rank := 'Capt';
seek(soldierfile,soldier-1); {reposition file pointer}
write(soldierfile,table[soldier]); {put back row}
closefile(soldierfile);
Using the first record for special purposes
There are many 'clever' things that can be built into Pascal data
files to make their management easier.
Prior to writing into a new file, seek the second component (thus
stepping over the first. Write all the components sequentially from
there, then seek the first component and place the number of written
components there. This allows you, the programmer to access the number
of records there are, rather than rely on an indefinite loop to do
the same thing. This method is commonly employed by programmers, but
relies on the components all being the same type (ie. a numeric field
would need to be part of the structure), and remembering to update
this number each transaction.
TEXT FILES
A text file is a sequential access file, that can be read and created
by many different applications. Most word processors, spreadsheet
programs and other utilities can use TEXT - this makes this file type
more generally applicable.
The drawback of using TEXT files is the speed of access - especially
during searching and editing
They are declared thus:
Var name : textfile;
A text file is a file containing sequences of characters delimeted
by called end of line (or EOLN) markers. Also, the
file terminates with an end of file marker (EOF).
NOTE: you cannot randomly access a text file, you must access the
stream of characters SEQUENTIALLY
eoln(filename) - answers true if the end of line in the file
has been encountered, otherwise it is false
eof(filename) -answers true if end of file encountered
read(filename, variable {,variable}) gets values from a file
note: the read statement in a text file retrieval does TYPING (ie.
interprets the incoming character stream to be of a particular data
type) depending on the types of variables the text is being read into
if the file contained the following ASCII characters:
abc 123 45.67
then the folowing read would be legal...
read(filename,char1, gstring, int1, real1)
where the following values would be retrieved:
char1 := 'a' ; gstring := 'bc'
int1 := 123 ; real1 := 45.67
readln(filename, variable {,variable}) reads values for variables
listed, then moves to the next line (skipping over that text not read
on the line)
write(filename, variable {,variable}) behaves as a write to
the screen does, including field width and decimal places, but places
text in the file without an end of line marker
writeln(filename, variable {,variable}) writes text as above
but also places an eol
Compound
Data Structures - FILES