Delphi文件管理(三)(转)

Delphi文件管理(三):

6.2.7 记录的删除、插入、排序 文件在最后一条记录前截断。 for i:=CurrentRec+1 to Count-1 do

  删除一条记录的基本思路是:获取当前记录的位置并把该位置后的记录逐个向前移动。

  

begin

seek(MethodFile,i);

read(MethodFile,MethodRec);

seek(MethodFile,i-1);

Write(MethodFile,MethodRec);

end;

Truncate(MethodFile); 

为避免误删除,在进行删除操作前弹出一个消息框进行确认。删除后要更新全局变量的值和显示内容: 

Count := Count - 1;

ChangeGrid; 

完整的程序如下: 

procedure TRecFileForm.DeleteButtonClick(Sender: TObject);

var

NewFile: MethodFileType;

MethodRec: TMethod;

NewFileName: String;

i: Integer;

begin

if FileOpened = False then Exit;

CurrentRec := StringGrid1.Row-1;

if CurrentRec < 0 then Exit;

if MessageDlg('Delete Current Record ?', mtConfirmation,

[mbYes, mbNo], 0) = idYes then

begin

HazAttr.text := '';

for I := CurrentRec+1 to Count-1 do

begin

seek(MethodFile,i);

read(MethodFile,MethodRec);

seek(MethodFile,i-1);

Write(MethodFile,MethodRec);

end;

Truncate(MethodFile);

Count := Count-1;

ChangeGrid;

end;

end;

  这里所显示的删除操作简单明了。但在程序开始设计时我却走了一条弯路,后来发现虽然这种方法用于记录的删除操作显得笨拙、可笑,但却恰恰是记录插入、排序的思想。

  这种思想的核心是创建一个新文件保存更新后的内容。若新文件顺利创建,则删除原文件,否则恢复原来的文件。程序清单如下: 

procedure TRecFileForm.DeleteButtonClick(Sender: TObject);

var

NewFile: MethodFileType;

MethodRec: TMethod;

NewFileName: String;

i: Integer;

begin

if FileOpened = False then Exit;

CurrentRec := StringGrid1.Row-1;

if CurrentRec < 0 then Exit;

if MessageDlg('Delete Current Record ?', mtConfirmation,

[mbYes, mbNo], 0) = idYes then

begin

HazAttr.text := '';

NewFileName := ChangeFileExt(FileName,'.sav');

try

AssignFile(NewFile,FileName);

ReWrite(NewFile);

Except

On EInOutError do

begin

Rename(MethodFile,FileName);

Exit;

end;

end;

for i := 1 to Count do

if I <> CurrentRec+1 then

begin

MethodRec := GridToRec(i);

Write(NewFile,MethodRec);

end;

closeFile(MethodFile);

try

AssignFile(MethodFile,Filename);

Reset(MethodFile);

except

on EInOutError do

begin

DeleteFile(FileName);

AssignFile(MethodFile,NewFileName);

Reset(MethodFile);

Rename(MethodFile,FileName);

Exit;

end;

DeleteFile(NewFileName);

Count:=Count-1;

ChangeGrid;

end;

end;

  对于记录插入,方法基本同上。对于排序,可先将关键域读入排序,而后再按排序结果对应的记录号顺序重写文件。 

6.2.8 结果综合 HazAttr只读编辑框中。

  对不同方法的评估结果,可按一定的公式进行综合。当用户按下“计算”按钮时,系统进行计算并把综合结果写入

  为保证结果显示的正确性,每次增加、修改、删除操作确认后HazAttr编辑框清空。 

6.2.9 编辑对话框的输入检查 TMethod的四个域。由于TMethodResult域必须是[0,1]间的小数,因此当用户按OK键关闭对话框时应进行类型和范围检查。VB中我做过同样的工作,那时需要对用户输入的键码逐个进行判断。但这种方法很繁琐、很难做圆满(如不能很好地支持编辑键)。而Object Pascal提供了更好的方法。这种方法的关键就在于它的类型转换函数Val: 

  当用户单击“增加”或“修改”按钮时系统将弹出一个编辑对话框,让用户输入或修改记录内容。其中的三个编辑框,一个组合列表框分别对应

  在

procedure Val(Str: String;var V; var Code: Integer); V是由Str转换成的整型或实型数。若字符串非法,则出错位置返至Code;否则置Code0。字符串非法并不会引发一个转换异常。

  

  如果转换后的数超出了我们的范围,则显式把Code置为-1。最后统一通过检测Code是否为0来判断输入是否合法。OnCloseQuery事件处理过程中。如输入非法,则禁止对话框关闭,并将输入焦点置于Result编辑框中。但假如用户按了Cancel按钮,则这种检查是多余的。为此定义一个布尔变量IsCancel,对话框生成时置为False。假如用户按下Cancel,则置为True,此时OnCloseQuery事件不进行输入检查。OnCloseQuery事件处理过程的程序清单如下: 

procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);

var

Res: Real;

k: Integer;

begin

if IsCancel = False then

begin

val(Result.text,Res,k);

if (Res > 1) or (Res < 0) then k := -1;

if k <> 0 then

begin

MessageDlg('非法输入 ',mtWarning,[mbOK],0);

Result.text := '';

CanClose := False;

Result.SetFocus;

end;

end;

end; 

6.2.10 文件和系统的关闭 CloseFile过程:  CloseFile(MethodFile); 

  文件关闭须调用

  

并对系统的状态重新进行设置。

系统关闭时首先检测当前是否有打开的文件。若有则先关闭文件。这在主窗口的OnCloseQuery事件中实现。

实现文件关闭的程序清单如下: 

procedure TRecFileForm.CloseButtonClick(Sender: TObject);

begin

if FileOpened then

begin

CloseFile(MethodFile);

FileOpened := False;

ClearGrid;

OpenButton.Enabled := True;

NewButton.Enabled := True;

CloseButton.Enabled := False;

RecFileForm.Caption := FormCaption;

end;

end; 

实现系统关闭前检查的程序清单如下:

procedure TRecFileForm.FormCloseQuery(Sender: TObject;

var CanClose: Boolean);

begin

if FileOpened then

closeFile(MethodFile);

end; 

6.2.11 记录文件小结 Delphi提供的文件管理函数。同时,为了保证程序的健壮性应对异常进行捕获并处理。在数据库应用技术发展的今天,记录文件的重要性也许有所下降,但对象我们这里所处理的简单问题它仍有用武之地。

  我们所举的例子虽然简单,但基本覆盖了记录文件操作的主要方面。这里关键问题在于灵活应用

  这里所举的例子一次只能处理一个文件。但读者可以很容易把它改为一个MDI程序。虽然对于这里的实际情况来说,似乎并无必要。 

6.3 文件控件的应用 Delphi文件管理的最大特色是提供了一组文件操作控件。利用这些控件我们可以快速开发一个文件名浏览系统。其功能强大与其所需书写代码之少所形成的强烈反差,正是Dephi生命力的体现。 

  

6.3.1 文件控件及其相互关系 Delphi提供的专用文件控件如下表所示。 6.4 Delphi专用文件控件━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  

   表

控件名

─────────────────────────────────────

DriveComboBox 驱动器组合列表框。用于选择当前驱动器

FileListBox 文件列表框。用于显示当前目录中的文件和选中当前文件

FilterComboBox 文件类型组合列表框。用于选择显示文件的类型

DirectoryOutline 目录树(6.4节专门介绍

)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Component Palette(部件选择板)的System页中,DirectoryOutline在Component PaletteSamples页中。

  以上控件前四个在

  以上文件控件再加上文件编辑框、目录标签框(事实上是一般的编辑框、标签框)就可以构成一个完整的文件操作系统。它们之间的联系几乎不用代码支持,只要设置好相应的属性就可以了。

  FileEditDirLabel、FileListBoxFileFilterComloList、 DirectoryListBoxDriveComboList六个控件间的属性联系如下: 

  DriveComboList .DirList := DirectoryListBox;

  

DirectoryListBox.FileList := FileListBox;

FileFilterComboList.FileList := FileListBox;

FileListBox.FileEdit := FileEdit; 

以上联系可以在设计时完成。只要打开相应属性的选择列表框进行选择即可。也可以在运行时利用如上的赋值语句建立联系。FileFilterComboList有一个Filter

属性,用来设置组合列表框的选择项; FileListBox 有一个 Mask 属性,用于设置显示文件的类型,这就允许 FileListBox在脱离FileFilterComboList 单独应用时仍能根据需要显示特定的文件。在 6.4节中我们将应用这一功能。

  文件控件的关键属性基本上都在以上联系中反映出来了。除此之外,

  文件控件的方法、事件基本是从ListBoxComboBox中继承的。但FileListBox中有一个ApplyFilePath方法很有用,我们将在后边给出其用法。 

6.3.2 文件名浏览查找系统的设计思路 

  作为文件控件的应用实例,我们开发了一个简单的文件名浏览查找系统。这个系统可用于文件名的显示,把选中的文件写入列表框,并能按文件编辑框中输入的通配符对文件进行查找。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

部件 属性 功能

─────────────────────────────────────

FileCtrForm Position=poDefault 主窗口

DirLabel 显示当前目录

FileEdit TabOrder=0 显示当前文件/输入文件显示匹配符

FileListBox1 FileEdit=FileEdit 显示当前目录文件

DirectoryListBox1 DirLabel=DirLabel 显示当前驱动器目录

FileList= FileListBox1

DriveComboBox1 DirList= DirectoryListBox1 选择当前驱动器

FilterComboBox1 FileList=FileListBox1 选择文件显示类型

Filter='All Files(*.*)|*.*|

Source Files(*.pas)|*.pas|

Form Files(*.dfm)|*.dfm|

Project Files(*.dpr)|*.dpr'

ListBox1 显示选中或查找的文件

Button1 Caption='查找' FileEdit 中的内容进行查找

Button2 Caption='退出' 退出系统

6.3.3 文件名浏览查找系统的功能和实现 

6.3.3.1 按指定后缀名显示当前目录中的文件 (6.3.1)中的介绍。 

  实现这一功能只需要在控件间建立正确的联系即可,不需要代码支持。建立联系的方法如

6.3.3.2 把选中的文件添加到列表框中 FileListBox1OnClick事件中: 

  在

procedure TFileCtrForm.FileListBox1Click(Sender: TObject);

begin

if Searched then

begin

Searched := False;

ListBox1.Items.Clear;

Label5.Caption := 'Selected Files';

end;

if NotInList(ExtractFileName(FileListBox1.FileName),ListBox1.Items) then

ListBox1.Items.Add(ExtractFileName(FileListBox1.FileName));

end;

  

函数NotInList用于判断待添加的字符串是否已存在于一个TStrings对象中。函数返回一个布尔型变量。

  

NotInList 的具体实现如下。 

Function TFileCtrForm.NotInList(FileName: String;Items: TStrings): Boolean;

var

i: Integer;

begin

for I := 0 to Items.Count-1 do

if Items[i] = FileName then

begin

NotInList := False;

Exit;

end;

NotInList := True;

end; 

Searched 是一个全局变量,用于标明 ListBox1当前显示内容是查找的结果还是从FileListBox1中选定的文件。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 

6.5 部件的设计 DirectoryListBox.DirLabel := DirLabel; 功能

  我们把输入检查放在对话框的

  对话框的


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10294527/viewspace-123294/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/10294527/viewspace-123294/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值