📄 017.htm
字号:
<HTML><HEAD><meta http-equiv="Content-Type" content="text/html; charset=GB2312"><TITLE>—DELPHI基础教程—第六章 文件管理(二)</TITLE><META NAME="keywords" CONTENT=" DELPHI基础教程 第六章 文件管理(二)"><META NAME="description" CONTENT=" - DELPHI基础教程 - 第六章 文件管理(二)"><style><!--#page {position:absolute; z-index:0; left:0px; top:0px}.tt3 {font: 9pt/12pt "宋体"}.tt2 {font: 12pt/15pt "宋体"}a {text-decoration:none}a:hover {color: blue;text-decoration:underline}--></style></HEAD><body text="#000000" bgcolor="#FFFFFF" leftmargin="3" topmargin="3" marginheight="3" marginwidth="3"><TABLE WIDTH="100%" CELLPADDING=10 CELLSPACING=0 BORDER=0><TR><TD CLASS="tt3" VALIGN="top" width="8%" ><strong><A HREF="018.htm"><FONT style="FONT-SIZE: 9pt">后一页</font></A><BR><A HREF="016.htm"><FONT style="FONT-SIZE: 9pt">前一页</font></A><BR><A HREF="index.html"><FONT style="FONT-SIZE: 9pt">回目录</font></A><BR></strong></TD><TD class="tt2" width="84%"><center><B><FONT style="FONT-SIZE: 16.5pt" COLOR="#FF6666" FACE="隶书">第六章 文件管理(二)</FONT></B></center><hr width="94%"><p>6.2.7 <font face="宋体" lang="ZH-CN">记录的删除、插入、排序 </p><p> 删除一条记录的基本思路是:获取当前记录的位置并把该位置后的记录逐个向前移动。</font><font face="宋体" lang="ZH-CN">文件在最后一条记录前截断。 </p><p> </font>for i:=CurrentRec+1 to Count-1 do</p><p>begin</p><p>seek(MethodFile,i);</p><p>read(MethodFile,MethodRec);</p><p>seek(MethodFile,i-1);</p><p>Write(MethodFile,MethodRec);</p><p>end;</p><p>Truncate(MethodFile);<font face="宋体" lang="ZH-CN"> </font></p><p><font face="宋体" lang="ZH-CN"> 为避免误删除,在进行删除操作前弹出一个消息框进行确认。删除后要更新全局变量的值和显示内容: </p></font><p>Count := Count - 1;</p><p>ChangeGrid; </p><p><font face="宋体" lang="ZH-CN"> 完整的程序如下: </p></font><p>procedure TRecFileForm.DeleteButtonClick(Sender: TObject);</p><p>var</p><p>NewFile: MethodFileType;</p><p>MethodRec: TMethod;</p><p>NewFileName: String;</p><p>i: Integer;</p><p>begin</p><p>if FileOpened = False then Exit;</p><p>CurrentRec := StringGrid1.Row-1;</p><p>if CurrentRec < 0 then Exit;</p><p>if MessageDlg('Delete Current Record ?', mtConfirmation,</p><p>[mbYes, mbNo], 0) = idYes then</p><p>begin</p><p>HazAttr.text := '';</p><p>for I := CurrentRec+1 to Count-1 do</p><p>begin</p><p>seek(MethodFile,i);</p><p>read(MethodFile,MethodRec);</p><p>seek(MethodFile,i-1);</p><p>Write(MethodFile,MethodRec);</p><p>end;</p><p>Truncate(MethodFile);</p><p>Count := Count-1;</p><p>ChangeGrid;</p><p>end;</p><p>end;</p><p><font face="宋体" lang="ZH-CN"> 这里所显示的删除操作简单明了。但在程序开始设计时我却走了一条弯路,后来发现虽然这种方法用于记录的删除操作显得笨拙、可笑,但却恰恰是记录插入、排序的思想。</font></p><font face="宋体" lang="ZH-CN"><p> 这种思想的核心是创建一个新文件保存更新后的内容。若新文件顺利创建,则删除原文件,否则恢复原来的文件。程序清单如下: </p></font><p>procedure TRecFileForm.DeleteButtonClick(Sender: TObject);</p><p>var</p><p>NewFile: MethodFileType;</p><p>MethodRec: TMethod;</p><p>NewFileName: String;</p><p>i: Integer;</p><p>begin</p><p>if FileOpened = False then Exit;</p><p>CurrentRec := StringGrid1.Row-1;</p><p>if CurrentRec < 0 then Exit;</p><p>if MessageDlg('Delete Current Record ?', mtConfirmation,</p><p>[mbYes, mbNo], 0) = idYes then</p><p>begin</p><p>HazAttr.text := '';</p><p>NewFileName := ChangeFileExt(FileName,'.sav');</p><p>try</p><p>AssignFile(NewFile,FileName);</p><p>ReWrite(NewFile);</p><p>Except</p><p>On EInOutError do</p><p>begin</p><p>Rename(MethodFile,FileName);</p><p>Exit;</p><p>end;</p><p>end;</p><p>for i := 1 to Count do</p><p>if I <> CurrentRec+1 then</p><p>begin</p><p>MethodRec := GridToRec(i);</p><p>Write(NewFile,MethodRec);</p><p>end;</p><p>closeFile(MethodFile);</p><p>try</p><p>AssignFile(MethodFile,Filename);</p><p>Reset(MethodFile);</p><p>except</p><p>on EInOutError do</p><p>begin</p><p>DeleteFile(FileName);</p><p>AssignFile(MethodFile,NewFileName);</p><p>Reset(MethodFile);</p><p>Rename(MethodFile,FileName);</p><p>Exit;</p><p>end;</p><p>DeleteFile(NewFileName);</p><p>Count:=Count-1;</p><p>ChangeGrid;</p><p>end;</p><p>end;</p><font face="宋体" lang="ZH-CN"><p> 对于记录插入,方法基本同上。对于排序,可先将关键域读入排序,而后再按排序结果对应的记录号顺序重写文件。 </p></font><p>6.2.8 <font face="宋体" lang="ZH-CN">结果综合 </p><p> 对不同方法的评估结果,可按一定的公式进行综合。当用户按下“计算”按钮时,系统进行计算并把综合结果写入</font>HazAttr<fontface="宋体" lang="ZH-CN">只读编辑框中。</p><p> 为保证结果显示的正确性,每次增加、修改、删除操作确认后</font>HazAttr<fontface="宋体" lang="ZH-CN">编辑框清空。 </p></font><p>6.2.9 <font face="宋体" lang="ZH-CN">编辑对话框的输入检查 </p><p> 当用户单击“增加”或“修改”按钮时系统将弹出一个编辑对话框,让用户输入或修改记录内容。其中的三个编辑框,一个组合列表框分别对应</font>TMethod<font face="宋体" lang="ZH-CN">的四个域。由于</font>TMethod<font face="宋体"lang="ZH-CN">的</font>Result<font face="宋体" lang="ZH-CN">域必须是</font>[0,1]<fontface="宋体" lang="ZH-CN">间的小数,因此当用户按</font>OK<font face="宋体"lang="ZH-CN">键关闭对话框时应进行类型和范围检查。</p><p> 在</font>VB<font face="宋体" lang="ZH-CN">中我做过同样的工作,那时需要对用户输入的键码逐个进行判断。但这种方法很繁琐、很难做圆满</font>(<fontface="宋体" lang="ZH-CN">如不能很好地支持编辑键</font>)<font face="宋体"lang="ZH-CN">。而</font>Object Pascal<font face="宋体" lang="ZH-CN">提供了更好的方法。这种方法的关键就在于它的类型转换函数</font>Val<fontface="宋体" lang="ZH-CN">: </p></font><p>procedure Val(Str: String;var V; var Code: Integer)<font face="宋体"lang="ZH-CN">; </p><p> </font>V<font face="宋体" lang="ZH-CN">是由</font>Str<font face="宋体"lang="ZH-CN">转换成的整型或实型数。若字符串非法,则出错位置返至</font>Code;<fontface="宋体" lang="ZH-CN">否则置</font>Code<font face="宋体" lang="ZH-CN">为</font>0<fontface="宋体" lang="ZH-CN">。字符串非法并不会引发一个转换异常。</p><p> 如果转换后的数超出了我们的范围,则显式把</font>Code<fontface="宋体" lang="ZH-CN">置为</font>-1<font face="宋体" lang="ZH-CN">。最后统一通过检测</font>Code<fontface="宋体" lang="ZH-CN">是否为</font>0<font face="宋体" lang="ZH-CN">来判断输入是否合法。</p><p> 我们把输入检查放在对话框的</font>OnCloseQuery<font face="宋体"lang="ZH-CN">事件处理过程中。如输入非法,则禁止对话框关闭,并将输入焦点置于</font>Result<fontface="宋体" lang="ZH-CN">编辑框中。但假如用户按了</font>Cancel<fontface="宋体" lang="ZH-CN">按钮,则这种检查是多余的。为此定义一个布尔变量</font>IsCancel<fontface="宋体" lang="ZH-CN">,对话框生成时置为</font>False<font face="宋体"lang="ZH-CN">。假如用户按下</font>Cancel<font face="宋体" lang="ZH-CN">,则置为</font>True<fontface="宋体" lang="ZH-CN">,此时</font>OnCloseQuery<font face="宋体" lang="ZH-CN">事件不进行输入检查。</p><p> 对话框的</font>OnCloseQuery<font face="宋体" lang="ZH-CN">事件处理过程的程序清单如下: </p></font><p>procedure TEditForm.FormCloseQuery(Sender: TObject; var CanClose: Boolean);</p><p>var</p><p>Res: Real;</p><p>k: Integer;</p><p>begin</p><p>if IsCancel = False then</p><p>begin</p><p>val(Result.text,Res,k);</p><p>if (Res > 1) or (Res < 0) then k := -1;</p><p>if k <> 0 then</p><p>begin</p><p>MessageDlg('<font face="宋体" lang="ZH-CN">非法输入</font> <font face="宋体"lang="ZH-CN">!</font>',mtWarning,[mbOK],0);</p><p>Result.text := '';</p><p>CanClose := False;</p><p>Result.SetFocus;</p><p>end;</p><p>end;</p><p>end; </p><p>6.2.10 <font face="宋体" lang="ZH-CN">文件和系统的关闭 </p><p> 文件关闭须调用</font>CloseFile<font face="宋体" lang="ZH-CN">过程: </p><p> </font> CloseFile(MethodFile); </p><p><font face="宋体" lang="ZH-CN">并对系统的状态重新进行设置。 </font></p><p><font face="宋体" lang="ZH-CN"> 系统关闭时首先检测当前是否有打开的文件。若有则先关闭文件。这在主窗口的</font>OnCloseQuery<fontface="宋体" lang="ZH-CN">事件中实现。</font></p><p><font face="宋体" lang="ZH-CN">实现文件关闭的程序清单如下: </p></font><p>procedure TRecFileForm.CloseButtonClick(Sender: TObject);</p><p>begin</p><p>if FileOpened then</p><p>begin</p><p>CloseFile(MethodFile);</p><p>FileOpened := False;</p><p>ClearGrid;</p><p>OpenButton.Enabled := True;</p><p>NewButton.Enabled := True;</p><p>CloseButton.Enabled := False;</p><p>RecFileForm.Caption := FormCaption;</p><p>end;</p><p>end; </p><p><font face="宋体" lang="ZH-CN">实现系统关闭前检查的程序清单如下:</p></font><p>procedure TRecFileForm.FormCloseQuery(Sender: TObject;</p><p>var CanClose: Boolean);</p><p>begin</p><p>if FileOpened then</p><p>closeFile(MethodFile);</p><p>end; </p><p>6.2.11 <font face="宋体" lang="ZH-CN">记录文件小结 </p><p> 我们所举的例子虽然简单,但基本覆盖了记录文件操作的主要方面。这里关键问题在于灵活应用</font>Delphi<fontface="宋体" lang="ZH-CN">提供的文件管理函数。同时,为了保证程序的健壮性应对异常进行捕获并处理。在数据库应用技术发展的今天,记录文件的重要性也许有所下降,但对象我们这里所处理的简单问题它仍有用武之地。</p><p> 这里所举的例子一次只能处理一个文件。但读者可以很容易把它改为一个</font>MDI<fontface="宋体" lang="ZH-CN">程序。虽然对于这里的实际情况来说,似乎并无必要。 </p></font><p align="center">6.3 <font face="宋体" lang="ZH-CN">文件控件的应用 </p><p> </font>Delphi<font face="宋体" lang="ZH-CN">文件管理的最大特色是提供了一组文件操作控件。利用这些控件我们可以快速开发一个文件名浏览系统。其功能强大与其所需书写代码之少所形成的强烈反差,正是</font>Dephi<fontface="宋体" lang="ZH-CN">生命力的体现。 </p></font><p>6.3.1 <font face="宋体" lang="ZH-CN">文件控件及其相互关系 </p><p> </font>Delphi<font face="宋体" lang="ZH-CN">提供的专用文件控件如下表所示。 </p><p> 表</font>6.4 Delphi<font face="宋体" lang="ZH-CN">专用文件控件━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</font></p><font face="宋体" lang="ZH-CN"><p>控件名</font> <font face="宋体" lang="ZH-CN">功能</font></p><p><font face="宋体" lang="ZH-CN">─────────────────────────────────────</p></font><p>DriveComboBox <font face="宋体" lang="ZH-CN">驱动器组合列表框。用于选择当前驱动器</p></font><p>FileListBox <font face="宋体" lang="ZH-CN">文件列表框。用于显示当前目录中的文件和选中当前文件</p></font><p>FilterComboBox <font face="宋体" lang="ZH-CN">文件类型组合列表框。用于选择显示文件的类型</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -