📄 pasl1013.html
字号:
<HTML><HEAD><LINK href="../style.css" rel="stylesheet" type="text/css">
<TITLE>Pascal Tutorial - Chapter 14</Title></head>
<body background="../tile01.jpg">
<H1><center>How About Binary One</center></h1><p><br><br><br><br>
Hello, we meet again! Nice to see ya! I know you're eager to finish this
last chapter of the first lesson. It's still about the file. It is similar
to the previous chapter. If you don't understand <a href="pasl1012.html">chapter 13</a>,
you'd better not carry on, but re-learn it instead. This time, we will discuss :<ol>
<li>Typed files</li><li>Untyped files</li><li>File commands</li>
<li>Directory commands</li></ol><p>There are two kinds of binary files :</p><ol>
<li>Typed files</li><li>Untyped files</li></ol><p>
Typed file means that the file has a uniform format throughout its contents.
This kind of file includes databases, because all of them contains
the data records. Simply said, file of records.
Untyped file means that the file contains no uniform data. Although you may
have seen records stored in this kind of file, that file contains some
additional information that may be different record structure. Simply said,
file with no distinct records.</p><p>
First, we discuss typed files. Suppose you define a record like this :</p>
<pre>
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
</pre><p>Typed file of THAT record is defined like this :</p><pre>
var
F : file of Temployee;
</pre><p>
The steps of using typed file is just the same as using text file.</p><ol>
<li>You associate it with file name using <tt>assign</tt>.</li>
<li>Open it, using <tt>reset</tt>, OR Create it, using <tt>rewrite</tt>.</li>
<li>Use it.<br><tt>Writeln</tt> in text file <b>MUST BE CHANGED</b> into
<tt>Write</tt> and <tt>Readln</tt> with <tt>Read</tt> respectively.</li>
<li>Close it using <tt>close</tt>.</li></ol><p>
All error handling and <tt>IOResult</tt> use is all the same, so that I don't have
to re-mention it all over again.</p><p>
The difference is : If you open typed file with <tt>reset</tt> it doesn't mean
that you can only read it (just in the text files), but you may write on it
and modify it. The command <tt>rewrite</tt> is still the same, create a new one,
discarding the file previous contents. Then, look at this example :</p><hr><pre>
{ A crude database recording }
uses crt;
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
var
F : file of Temployee;
c : char;
r : Temployee;
s : string;
begin
clrscr;
write('Input file name to record databases : '); readln(s);
assign(F,s); { Associate it }
rewrite(F); { Create it }
repeat
clrscr;
write('Name = '); readln(r.name); { Input data }
write('Address = '); readln(r.address);
write('Phone = '); readln(r.phone);
write('Age = '); readln(r.age);
write('Salary = '); readln(r.salary);
write(F,r); { Write data to file }
write('Input data again (Y/N) ?');
repeat
c:=upcase(readkey); { Ask user : Input again or not }
until c in ['Y','N'];
writeln(c);
until c='N';
close(F);
end.
</pre><hr><p>
Easy, right ? After creating database, display it. Modify the above program
to read the file contents. This is the hint :</p><ol>
<li>Change <tt>rewrite</tt> to <tt>reset</tt>.</li>
<li>After the second <tt>clrscr</tt> (inside <tt>repeat..until</tt> block), add : <tt>read(F,r);</tt></li>
<li>Remove the line "<tt>write(F,r)</tt>"</li></ol><p>
That's all. You may alter the displayed message to the appropriate one. Run
it and see how it's done. Good ! You've done it !</p><p>
Now, it's time to understand file pointer. In order to know the current position
of the file, Pascal use a file pointer. It's simply points to the
next record or byte to read. To move the file pointer, use <tt>seek</tt> :</p><pre>
seek(F,recordno);
</pre><p>
The <tt>recordno</tt> simply said the record number. If you want to read the tenth
record of the file at any instant, use this :</p><pre>
seek(F,9); { Data record number started from 0 }
read(F,r); { r is the record variable }
</pre><p>
You may conclude that it is easy to access the records. Say the record number,
seek it, and read it. Any record number in range could be accessed.
In range means not exceeding the maximum number of record inside that file.
Therefore, it is called <b>Random File Access</b>.</p><p>
In the other hand, text files could not behave like that. So that it requires
to be handled sequentially. Therefore, there comes the jargon <b>Sequential
File Access</b>.</p><p>
Append DOES NOT work in typed files or untyped files. It is specially designed
for text files. Then how can we append data to typed files ? Easy.
Follow these steps :</p><ol>
<li>Open the file with <tt>reset</tt>.</li>
<li>Move the file pointer after the last record using seek.</li></ol><p>
<tt>Reset</tt> causes file opened but the file pointer points to the first record.
How can we know the number of records that is stored inside a file ? Number
of records can be calculated as follows :</p><pre>
totalrecord := filesize(f);
</pre><p>
Here is an example of a 'crude' database. It creates a new database if it
is not exist, otherwise it appends data.</p><hr><pre>
{ A crude database recording }
uses crt;
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
var
F : file of Temployee;
c : char;
r : Temployee;
s : string;
n : integer;
begin
clrscr;
write('Input file name to record databases : '); readln(s);
assign(F,s); { Associate it }
{$I-}
reset(F); { First, open it }
{$I+}
n:=IOResult;
if n<>0 then { If it's doesn't exist then }
begin
{$I-}
rewrite(F); { Create it }
{$I+}
n:=IOResult;
if n<>0 then
begin
writeln('Error creating file !'); halt;
end;
end
else { If it exists then }
seek(F,filesize(F)); { Move file pointer to the last record }
repeat
:
:
:
{ All remains the same }
:
:
</pre><hr><p>
Now, how can we delete a data ? The only routine that Pascal provides is
<tt>Truncate</tt>. It deletes all data starting from where file pointer points to
the end of file. You may wonder how to delete a single data record. This is
how : Suppose the record number you want to delete is stored in n.</p><pre>
for i:=n to totalrecord-1 do
begin
seek(f,i);
read(f,r);
seek(f,i-1);
write(f,r);
end;
seek(f,totalrecord-1);
truncate(f);
dec(totalrecord);
</pre><p>
Yes, you move the next record to the deleted record. The second next to the
next and so on until the end of data. After that, you can safely truncate
the last record, since the last record is already stored in record number
<tt>totalrecord-1</tt> and the last record would be a mere duplicate. Last step you
must make is that you must adjust the totalrecord to comply with present
situation (after deletion).</p><p>
Easy, right ? Oh, yes ! I forgot to mention : Flush cannot be applied to
binary files. It's just for text files.</p><p>
It is unpractical to always having file pointer tracked. You can obtain the
file pointer position by using <tt>filepos</tt> :</p><pre>
n:=filepos(F);
</pre><p>N will hold the current file position (the record number).</p><p>
That's all about typed files. You may want to see this program for better
details. Run it and learn how it works.</p><hr><pre>
{ A crude database recording }
uses crt;
type
Temployee = record
name : string[20];
address : string[40];
phone : string[15];
age : byte;
salary : longint;
end;
var
F : file of Temployee;
c : char;
r : Temployee;
s : string;
n : integer;
begin
clrscr;
write('Input file name to record databases : '); readln(s);
assign(F,s); { Associate it }
{$I-}
reset(F); { First, open it }
{$I+}
n:=IOResult;
if n<>0 then { If it's doesn't exist then }
begin
{$I-}
rewrite(F); { Create it }
{$I+}
n:=IOResult;
if n<>0 then
begin
writeln('Error creating file !'); halt;
end;
end
else
begin { If it exists then }
n:=filesize(F); { Calculate total record }
seek(F,n); { Move file pointer PAST the last record }
end;
repeat
clrscr;
writeln('File position : ',filepos(f));
write('Name = '); readln(r.name); { Input data }
write('Address = '); readln(r.address);
write('Phone = '); readln(r.phone);
write('Age = '); readln(r.age);
write('Salary = '); readln(r.salary);
write(F,r); { Write data to file }
write('Input data again (Y/N) ?');
repeat
c:=upcase(readkey); { Ask user : Input again or not }
until c in ['Y','N'];
writeln(c);
until c='N';
close(F);
end.
</pre><hr><p>Before you fully understand typed files, <b>DO NOT CONTINUE</b> to untyped one, it
will just make you more confused.</p><p>
Text files are usually used for INI files or setting files. Or, if your
game needs special setup, you can use this skill to modify AUTOEXEC.BAT,
CONFIG.SYS or even *.INI in WINDOWS directory.
Typed files are usually done for recording high scores of your game, while
untyped ones are for reading your game data : pictures, sounds, etc.
Serious applications make an extensive use of file. Databases usually use
typed files. Text files are used for making memos. Untyped ones is for
reading pictures and sounds, for perhaps, you want to make presentations or
just displaying the company logo.</p>
<h3>Untyped Files</h3>
<p>Now, we're going to discuss the untyped files. The basics is all the same.
Imagine you have a typed file, but the record is one byte long.
The declaration is a bit different from typed files :</p><pre>
var
F : file;
</pre><p>
This declare F as untyped files. <tt>Assign</tt> and <tt>Close</tt> are still the same, but
<tt>Reset</tt> and <tt>Rewrite</tt> are a little bit different. Instead of just passing
the <tt>F</tt>, you have to specify the "record size" for that file like this:
<pre> reset(F,1);
</pre>
<p><tt>Rewrite</tt> is just similar. What is the "record size" for?
It is used to specify the number of bytes each time you read or write from that file.
Let me explain that a bit later.
<p>The command <tt>write</tt> and <tt>read</tt> cannot be used in untyped file. Use
<tt>blockwrite</tt> and <tt>blockread</tt> instead. Here is the syntax :</p><pre>
blockread (f,buffer,count,actual);
blockwrite(f,buffer,count,actual);
f is the file variable.
buffer is your own buffer, not Pascal's.
count is the number of records you want to read/write.
actual is the number of bytes that has been read/written.
</pre>
<p>The parameter <tt>count</tt> in both commands will determine how many records (not bytes)
you will read or write. Effectively, the total number of bytes (read or written)
is <tt>count*record_size</tt> bytes. This is why you <b>must</b> set the record size
in the first place because Pascal doesn't know that.
<p>In untyped files, you must prepare a buffer. A buffer can be records,
arrays, or even pointers. Usually, programmers use array instead of records.
But, usually, if the file has certain structure, like graphic formats,
programmers use records. Let's first concern about array as the buffer.
Suppose I declared buffer as array of bytes :</p><pre>
var
buffer : array[1..2048] of byte;
count, actual : word;
f : file;
</pre>
<p>Since we have an array of bytes for the buffer, we have to set the record size
to 1. We can simply consider that each array element counts as one byte. If you have
array of integers or words, you may as well set the record size into 2.
<p>Reading is done by this :</p>
<pre>
:
reset(f,1); { Setting record size to 1 }
:
:
count:=sizeof(buffer);
blockread(f,buffer,count,actual);
</pre>
<p>This example will read 1*2048 bytes because record size is set to 1 and the size
of the buffer (specified in <tt>count</tt>) variable is 2048.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -