如果想使用Delphi开发一个简单的保存数据的程序,但又不想直接使用文本文件,因为文本文件的安全性太差了,拿个记事本就可以打开随便修改,那么你可以试试二进制文件(它以内存中数据的二进制编码形式存储数据)。
在Delphi中有三种类型的文件:二进制文件(也叫类型文件)、文本文件(也叫ASCII文件)和随机文件(也叫无类型文件)。二进制文件是由一批同一类型的数据组成的一个数据序列,就是说一个具体的二进制文件只能存放同一种类型的数据。文本文件以字符的ASCII码形式存放信息。随机文件不对文本的数据结构作任何定义,认为文件就是由一系列字节组成,直接访问磁盘文件的低级通道。
文本文件每个记录行的长度以及数据类型可以不一样,由回车还行符作为记录结束标志;二进制文件包含了由特定类型的数据结构定义的数据,例如下面的例子,首先定义了记录类型TMember,然后定义了基类为TMember的数组变量Members,接下来本文要使用这个类型存储某个 Delphi论坛的成员信息。
type
TMember = record
Name : string[10];
eMail : string[20];
Posts : LongInt;
end;
var Members : array[1..50] of TMember;
向磁盘存储信息之前我们需要定义一个二进制类型文件的变量名,下面的代码声明一个名为F的类型文件变量。
var F : file of TMember;
注意:在Delphi中,为了建立一个二进制文件,需要使用这样的语法:var SomeTypedFile : file of SomeType ;
这个文件的基类型(SomeType)可以是标准类型(比如整型),也可以是数组或记录类型,但是不能为长字符串、动态数组、类、对象或者是一个指针。
为了在Delphi中使用这个文件,我们必须把这个文件变量和磁盘上的实际文件建立关联,这个关联可以使用AssignFile过程来建立,本文使用如下代码把磁盘上的文件“Members.dat”和文件变量名“F”建立关联:
AssignFile(F, 'Members.dat') ;
一旦磁盘上的外部文件已经确定,这个文件变量“F”就可以打开它用于读写的操作。我们可以通过Reset过程打开一个已经存在的文件或者Rewrite过程新建一个文件。一旦文件处理完毕,我们必须通过CloseFile过程关闭这个文件。当文件关闭以后,文件变量的外部关联就被切断,可以和其他文件重新建立关联。
一般来说,我们总是要使用异常处理,因为针对文件操作可能会出现很多错误。比如,对一个已经关闭的文件调用CloseFile过程,Delphi 就会报告I/O错误;试图打开一个没有调用AssignFile的文件,Delphi就会报告不可预测的错误。
假设我们已经填完一组Delphi论坛上用户的姓名、Email和发贴数量等信息,接下来的代码可以将在磁盘上新建一个名为“Members.dat”的文件,并将论坛用户信息保存在文件中。
var F : file of TMember;
i : integer ;
begin
AssignFile(F,'Members.dat');
Rewrite(F);
try
for i:= 1 to 50 do Write (F, Members[ i ]);
finally
CloseFile(F);
end;
end;
为了处理“Members.dat”文件记录的所有数据,必须使用如下形式的代码:
var Member: TMember
F : file of TMember;
begin
AssignFile(F,'Members.dat');
Reset(F);
try
while not Eof(F) do begin Read (F, Member);
{这里可以对论坛成员信息进行相关处理}
end;
finally
CloseFile(F);
end;
end;
上面用到的Eof函数是用来检查是否到文件结束位置的,调用这个函数是为了避免到文件结束处(最后一条记录结束处)之外读取记录。
一般情况下文件是被顺序读取的,如果用标准的Read过程来读取文件或者标准的Write过程来写文件的话,当前位置总是按照顺学一条记录一条记录的向后移动。二进制文件还可以使用标准的Seek过程实现随机访问,Seek过程可以指定文件当前位置的跳转。利用FilePos函数和FileSize函数可以返回文件的当前位置以及当前文件的大小(就是记录的条数)。
{返回到文件开头也就是第一条记录开始处}
Seek(F, 0);
{直接到第五条记录处}
Seek(F, 5);
{到文件结尾处也就是最后一条记录结束的地方}
Seek(F, FileSize(F));
以上我们一直是在读取或者写入整个论坛成员的记录。那么如何改变第十个成员的Email地址呢?下面是比较标准的做法:
procedure ChangeEMail(const RecN:integer; const NewEMail:string);
var DummyMember : TMember;
begin
{这里省略assign以及出错处理模块}
Seek(F, RecN);
Read(F, DummyMember);
DummyMember.Email := NewEMail;
{读取后移动到下一条记录,我们必须返回到原来位置再进行写入}
Seek(F, RecN);
Write(F, DummyMember);
{这里省略关闭文件模块}
end;
通过以上介绍的方法,我们可以把论坛成员的信息直接写入硬盘文件,可以读取成员信息,还可以从文件中间改变某个成员的信息。更为重要的是,我们保存的信息不是文本文件,比如记事本打开一个含有两条成员信息的文件,可能类似于以下的形式:
王甲春 jiachun@bjn2ms.net X 老猫 webmaster@bjn2ms.net?
你可能注意到,有些信息已经不是正常的文本形式,那么进一步扩展一下你就可以利用二进制文件进行数据加密的存储了。