第7章VB文件系统 7.1基本要求 1.掌握文件系统的三个控件驱动器列表框、目录列表框和文件列表框的使用: 2.掌握顺序文件的读写操作: 3.掌握随机文件的读写操作。 7.2知识点 1.文件系统控件 VB中的文件系统控件包括驱动器列表框、目录列表框和文件列表框: (1)驱动器列表框(DriveListBox):用来显示当前机器上的所有盘符。 ①Drive属性:用户可以用代码检查Drive属性来判断当前选择的驱动器,也可通过代 码指定出现在列表框顶端的驱动器。 ②Change事件:驱动器列表框的Change事件是在选择一个新的驱动器或通过代码改 变Drive属性的设置时发生。 (2)目录列表框(DirListBox):用来显示当前盘上的所有文件夹。 ①Path属性:该属性用来返回或设置当前文件夹的路径,只能在程序运行中使用。 ②Change事件:目录列表框的Change事件是在双击一个新的目录或通过代码改变Path 属性的设置时发生。 (3)文件列表框(FileListBox):用来显示当前文件夹下的所有文件名。 ①Path属性:该属性用于返回或设置运行时选择的路径以显示其下的文件,默认路径 为当前路径。改变Dir属性会触发PathChange事件。例如代码“Filel.Path=Dirl.Path”可以 设置在目录列表框中选中的路径为文件列表框的当前路径 ②Pattern属性:该属性用来确定程序运行时列表框中显示哪些类型的文件。在参数中 可以使用分号“,”来分割多种文件类型例如“*.exe;*.bmp”。 ③FileName属性:该属性返回或设置所选文件的路径和文件名。比如,我们要在窗体 启动 ④PathChange事件:当文件列表框的Path属性改变时发生PathChange事件。 ⑤PattenChange事件:Pattern属性改变时发生PattenChange事件。 ⑥Click事件当选择一个新的文件时触发Cick事件。 2.几个关于文件的基本概念 (1)字符(Character):字符是数据的最小单位,可以是数字、字母、特殊符号或单一 字节。这里所说的“字符”一般为西文字符,一个西文字符用一个字节存放。如果为汉字字 符,则通常用两个字节存放。即一个汉字字符的存储大小相当于两个西文字符的存储大小。 (2)字段(Field):字段是指由几个字符组成的一项数据。 (3)记录(Record):记录是由一组相关的字段组成,在数据库中处理数据是以记录为 单位。 (4)文件(File):文件由一个或一个以上的记录集合而成。 3.顺序访问文件 顺序文件是一系列的ASCⅡ码格式的文本行,数据按顺序排列存放,与文档中出现的 顺序相同。每行的长度可以变化,是最简单的文件结构,任何文本编辑器都可以读写这种文 件
! "# $ %& % &$'()*+ ,-./0 1 23 456789: 23'; ?@5AB7 8CDEFGHI J K KLG=>M N OAB78P Q 23RSTUV %&% &$'()*+/,-.W 1 23X23'YZORS*+W[\?]^G_`a! J K KLGbcM NOAB78PQ 23RSTUV %&% &$'()*+Wd-.e 1 23$X23fYZORS`aT=>[\6()gd?hi[\ j*+[\ PQ 23klU K mn78o p56 RSG!=![\j*+[\ J 23$X23'qD_`aT!()rstu Gvw! 56xyop'xz{|tumno !p } " 23$X23YZORS-=[\e ~n?G K$* 23PQTUV K K$ 23PQTUV K #$ K*=>M NTlU #$ K %&0% # &$0Lw?56Lw0yOM -o0pMj0?M 0M nj 0?A M 0 ¡*f 0 %&¢% %&$¢LC£¤ 0¥¦M§w %&¨%& # %&$¨L£M¥¡©¢¥¦?Gwª!«¬wL6¨j %'&% &$£M OM 6,¨®¯¦ LM ()** 8°±²a?w³´?µ¶!EF ¡· ¸a¹º56Q»?L¼½¾?¿À²Á Ã56|
(1)打开文件语句(Open) Open语句分配一个缓冲区供文件进行I/O之用,并决定缓冲区所使用的访问方式。 语法格式: Open文件名For模式[Access存取类型][锁定]As#]文件号[Len=记录长度] 文件名(Filename):指定需打开的文件名称,该文件名可能还包括目录、文件夹及驱 动器。 模式(Mode):指定文件访问的方式,有Append(从文件末尾添加)、Binary(二进制)、 Input(顺序输入)、Output(顺序输出)、或Random(随机)方式。如果未指定方式,则以 Random方式打开文件。 存取类型(Access):可选项。说明打开的文件可以进行的操作,有Read(只读)、Write (只写)、或Read Write(读写)操作。 锁定(Lock):可选项。说明限定于其它进程打开的文件的操作,有Shared(共享)、 Lock Read(防止读出)、Lock Write(防止写入)、和Lock Read Write(防止读出与写入)操 作。 文件号(filenumber):是整型表达式,范围在1-5l1之间。在执行Open语句时,文件 与分配的文件号相关联。所有当前使用的文件号都必须唯一。 记录长度(reclength):可选项。是整型表达式,小于或等于32767字节,是缓冲区字 符数,默认值为512个字节,对于用随机访问方式打开的文件,该值就是记录长度。对于顺 序文件,该值就是缓冲字符数,不适用于二进制访问的文件。 (2)关闭文件语句(Close) 关闭Open语句所打开的输入/输出(/O)文件。 语法格式: Close[[#]文件号][,[#]文件号].J 说明: 若省略文件号,则将关闭Open语句打开的所有活动文件。当关闭Output或Append打 开的文件时,将属于此文件的最终输出缓冲区写入操作系统缓冲区,所有与该文件相关联的 缓冲区空间都被释放。在执行Clos肥语句时,文件与其文件号之间的关联将终结。 (3)写文件 ①Print语句 功能:将格式化显示的数据写入顺序文件中。 语法:Print#文件号,[outputlist] 说明: outputlist:可选的。是指表达式或是要打印的表达式列表。 ②Write语句 功能:将数据写入顺序文件中。 语法格式:Write#文件号,[outputlist] 说明: outputlist:可选的。是指要写入文件的数值表达式或字符串表达式,用一个或多个逗号 将这些表达式分开。 (4)读文件 ①Input语句: 功能:从己打开的顺序文件中读出数据并赋给变量。 语法格式:Input#文件号,变量列表 说明:变量列表由一个或多个变量组成,可以是简单变量、数组元素和用户定义类型的
%&ÄÅÆÇ%+! & +! ÆÇxÈM ÉÊËÌÍa *,+ Î?ÏÐDÉÊË-ÑÒÓ± ÆÔ°±$ +! e Õ± -(## Ötu.×ØDÙ(-/.y× Ú¨¹ºÙ e% &$CDÛÄÅeÜ?Xe5^Ý"#WÞ Õ±%0% &$CDÑÒÓ±?. (!! %%ßàáâã& 1%äÍå& *!2%æç&+2!2%æE&O &% %&Ó± nèCDÓ±?6 &% Ó±ÄÅ Ötu%(## &$5=§ éÄÅ56Ía?. & %%]&3 %]&O & %3 %& ØD%#$&$5=§ éêDfgëÍ_ÄÅ?. ) %%ìí& #$& %%îïE&#$3 %îïç& #$& %3 %îïEµç& y%4 2 &$Lðuñ±?òóG 56 Îô Gõa +! ÆÇT? µxÈy¡©ö -.*+yÃ÷øùM ¨¹º% # &$5=§ Lðuñ±?fOúf 7 ?LÉÊË 0w?hiûj 6 ?üfÑÒÓ±ÄÅ?XûýL¨¹º üf ?XûýLÉÊ0w?þfäÍåÑÒ %&©ÆÇ% & © +! ÆÇ-ÄÅæç,æE8*,+9 ÆÔ°±$ -- ×Ùy.-: ×Ùy.. é$ y?© +! ÆÇÄÅ-. *© +2!2 O (!! % Ä ÅT?2f æEÉÊËçÉÊË?-.µX¡©ö ÉÊËôà Gõa ÆÇT?µgyÎô©ö ½ %& 1 ÆÇ ^$°±»()wç! ÆÔ$ y?-2!2. é$ 2!2$5= LCñ±OLÄñ± J 3 ÆÇ ^$wç! ÆÔ°±$3 y?-2!2. é$ 2!2$5= LCçwûñ±O0ñ±?M O{ y sñ±xÅ %'& 1*!2 ÆÇ$ ^$ßÄÅ!EwÏQ ÆÔ°±$*!2 y?Q é$Q£M O{ Q¥¦?56L¼Qw¥4Dtu
元素,用逗号分隔开多个变量。 ②Line Input#语句: 功能:Line Input用于从己打开的顺序文件中读出一行数据,并赋给String变量或Variant 变量。 语法:Line Input#文件号,变量名 说明:通常用Print#将Line Input#语句读出的数据写入文件。 4.随机文件的访问 随机文件每个记录都有一个记录号,可以根据记录号访问文件中的任何一个记录。 (1)声明变量 首先应声明所有用来处理该文件数据的变量,包括标准类型和用户自定义类型的变量。 如果需要打开的随机文件是由多个字段的记录组成,可以采用用户自定义类型的变量对应文 件中的记录。在标准模块中使用“Type…EndType”语句定义一个用户自定义类型。 (2)打开随机文件(Open) 语法格式:Open文件名[ForRandom]As文件号[Len=记录长度] 说明: 在打开方式中应指明以Random方式打开,Random是默认的访问类型,可以用不同的 文件号打开同一个文件。 记录长度默认值为128个字节。每个记录的长度是将各字段所占的字节数相加,如果记 录长度比文件记录的实际长度短,则会产生一个错误:如果比记录的实际长度长,则会浪费 磁盘空间。 (3)关闭随机文件(Close) 语法和顺序文件相同。 (4)写操作 语法格式:Put[#]文件号,[记录号],变量名 说明: Pt#语句用于将变量的内容写入磁盘文件中,进行记录的添加或替换。 记录号是指明在此记录号开始写入。如果省略记录号,则为最近一个Gt或Put语句的 (或上一个Seek语句指出的)下一个记录。 变量名是要写入磁盘的数据的变量名,其数据类型应与记录类型一致。 通常用Get将Put写入的数据读出来。 (5)读操作 语法格式:Get扪文件号,[记录号],变量名 说明: 用Gt#语句将一个己打开的磁盘文件读出到一个变量。读出数据时所用的数据类型必 须与建立文件时所用的数据类型一致。 7.3疑难解析 1.文件系统的三个控件不能自动产生关联 文件系统的三个控件不能自动产生关联,也就是当驱动器改变时,目录列表框不能跟着 相应改变:或者当目录列表框改变时,文件列表框不能跟着相应改变。要三个控件产生关联, 使用下面两个事件过程: Private Sub Drivel_Change() Dir1.Path Drive1.Drive End Sub
?yxÅ{ Q J *!2ÆÇ$ ^$ *!2 fßÄÅ!EMaw?Ï ) QO Q ÆÔ$ *!2y?Qe é$A / *!2/ ÆÇEwç ¸ ¨Ã.M ¨y?56¨yÑÒ!¿ÀM ¨ %&éQ é-.'«¬XwQ?"# tu4!DtuQ nÛÄÅL£{ ¢¨¥¦?56"4!DtuQü !¨ G Õ#!o;1! $ O 2 ÆÇ %O,M ) $ ÆÇCE&dM ¨ QeLç//wQe?gwtuµ¨tuM6 A > 2 çwE' %6& ÆÔ°±$> -/.y?-¨y.?Qe é$ > /ÆÇM ÄÅ//E7M Q EwT-wtu÷ øµ89T-wtuM6 þ^!*V©ö?@ýL* PQT?þ^:; ¡PQO<*PQT?þ^:;¡PQ *V©ö? d= KB_$ )2 ? 89 <%)2
Private Sub Dirl Change( Filel.Path=Dir1.Path End Sub 2.如何在目录列表框表示当前选定的目录 在程序运行时双击目录列表框的某目录项,则将该目录项改变为当前目录,其Dirl.Path 的值做相应的改变。而当单击选定该目录项时,Dir1.Path的值并没有改变。为了对选定的 目录项进行有关操作,即与ListBox控件中某列表项的选定相对应,则表示如下: Dir1.List(Dir1.ListIndex) 3.当使用文件系统控件对文件进行打开操作时,显示“文件未找到”出错信息 例如,如下语句:Open Filel..Path+File1.FileName For Input As#l 当选定的目录是根目录,上述语句执行正确:而当选定的目录为子目录,上述语句执行 时显示“文件未找到”出错信息。 其中:Filel.Path表示当前选定的路径,Filel.FileName表示当前选定的文件,合起来表 示文件的标识符。 当选定的文件在根目录下(假定驱动器为C),Flel.Path的值为“C:1”,假定选定的文 件名为“tmp.txt”,则File1..Path+File1.FileName的值为“C:tmp.txt”,为合法的标识符。 当选定的文件在子目录下(假定驱动器为C,子目录为my),Filel.Path的值为“C:”, 假定选定的文件名为“tmp.txt”,则Filel.Path+Filel.FileName的值为“C:mytmp.txt”,子目 录与文件名之间少了一个“1”分隔符,所以为不合法的标识符。 为了保证程序的正常运行,应采用选择结构来处理这两种情况,故语句:Open Filel.Path +Filel.FileName For Input As#1应改为如下程序段: If Right(File1.Path,1)="\"Then Open Filel.Path Filel.FileName For Input As #1 Else Open File1.Path +"\"Filel.FileName For Input As #1 End If 4.Ope语句中欲打开的文件名是字符串常量也可以是字符串变量,但使用者概念不 清,导致出现“文件未找到”出错信息 例如,要从盘上读入文件名为“C:\my\tmp.txt”, 文件名是字符串常量时,对应程序段书写如下: Open "C:\my\tmp.txt"For Input As #1 但常见到错误的写法有: Open C:\my\tmp.txt For Input As #1 少写了作为字符串常量的文件名两端的引号“”: 文件名是字符串变量时,对应程序段书写如下: strFile="C:\my\tmp.txt" Open strFile For Input As #1 但常见到错误的写法有: strFile="C:\my\tmp.txt" Open "strFile"For Input As #1 多写了存储文件名的字符串变量的两端的引号“”。 5.文件没有关闭又被打开时,显示“文件己打开”的出错信息 例如,下列语句:
)2 ? 89 §?X§PQj*+?g û?¡PQ ¯*c=DX§T? ûÏ@.PQ jAü=D §Ía.©?µ !>§=D¡ü?)nd$ 8 *% 9 &*+,-./012345%6789:; mn?ndÆÇ$+! @ " *!2(/ *=DL?,BÆÇõaCq¯*=DjD?,BÆÇõa T()oèE7pE+FG g!$ )*+=D[\? " )*+=D?®H' )I0 *=DGd%JD j &? ûjoAp?JD=D ejo !p? @ " ûjoA !p?j®ÔI0 *=DGDd%JD j ?Dj 1&? ûjoAp? JD=Dejo !p? @ " ûjoA 1 !p?D µeÎôKAM oApx0?-6jþ®ÔI0 jALM_C`a?"=>½¾'«¬|NO?PÆÇ$+! @ " *!2(/ Pjnd_¢$ *4&8 :9BAB; +! @ " *!2(/ mn?ß/,çejoA 1A !p? eL0T?ü_¢Qnd$ +! BA 1A !B *!2(/ RS7+,Ô.$ +! A 1A ! *!2(/ KAj0eITyop eL0QT?ü_¢Qnd$ BA 1A !B +! *!2(/ RS7+,Ô.$ BA 1A !B +! B B *!2(/ {Ae0QITyop TUVWX/0345%6Y/0: ; mn?dÆÇ$
Private Sub Command1_Click() Open "c:\text.txt"For Input As #1 Line Input #1,x Print x End Sub 当再次单击命令按钮Commandl时,会显示“文件已打开”的出错信息,解决方法是 在Print x语句后写上Close#1,即打开的文件操作完毕后应及时关闭。 6.当利用Input(LOF(#文件号),文件号)语句一次读入顺序文件时,遇到“输入 超出文件尾”的错误信息。 主要是LOF(#文件号)函数获得文件内容的字节数,它是以Windows系统对字符采用 DBCS码,即西文是单字节,中文是双字节:而Input(LOF(#文件号),文件号)语句读 的是文件的字符数,在VB中一个西文字符和一个汉字均为一个字符。当文件内容中含有汉 字时,在使用:Iput(LOF(#文件号),文件号)函数时,会遇到输入超出文件尾”的错误 信息。 为了防止此类错误的发生,一般利用Line Input语句逐行读入最安全。 7.随机文件的记录类型不定长,引起不能正常存取。 随机文件是按记录为单位存取的,而且每条记录长度必须固定,一般利用Typ爬定义记 录类型。当记录中的某个成员为String时,必须确定其长度,即String*n,n是常数:否则 要影响对文件的存取。 8.如何读出随机文件中的所有记录,但又不知道记录号 一般,随机文件按记录号读取,当不知道记录号或者要全部读出记录时,则只要同顺序 文件一样的读取方法,采用循环结构加无记录号的Gt语句即可,程序段如下: Do While Not EOF(1) Get #1,,i Print i; Loop 随机文件读/写时可不写记录号,表示读时自动读下一条记录,写时插入到当前记录后。 7.4典型例题 例7-1编写统计文件“C:\filel.dat”中字母出现的次数(不区分大小写)。提示: 每次从文件中读取一个字符,判断是否是字母。若是字母,计数器加1。 解答: (1)新建工程,在窗体上添加1个命令按钮。 (2)为命令按钮编写单击事件过程,实现从文件中读取一个字符,判断是否是字母, 并计数,并在窗体上打印输出。 Private Sub Command1 Click() Dim num As Integer,c As String *1 num =0 Open "c:\file1.dat"For Input As #2 Do While Not EOF(2) c Input$(1.#2) '读取一个字符 c=UCase(c) Ifc>="A"And c="a"And c<="z"Then
)2 %?#$89 +! B#A B *!2(/ *!2/: g ^L +%/y&_w`a01w?ëL6 3%C ü0" ) 8?L?!Lb¯ *!2%+%/y&?y&ÆÇ L0w?G !M 0M bjM 0 *01!c. T?G$*!2%+%/y&?y&_wT?kd7æçeEáp+, FG jAîï t+,UV?Mf *!2 ÆÇgaçhi h!ij)k4lmnHopg L³¨jÖ?¯j¸k¨¹º÷ølD?Mf ;1! D¨ tu *¨!> ¦mj ) T?÷øqDg¹º? ) ? Lwn opüÖ `;A qUh!4NWrsh!\ M?³¨yÖ?*þqr¨yO ÆÇ5?_¢nd$ 3 " /:: ! ,T5þ¨y?)T!dMk¨?Txç7*+¨[ ' m 5 Áyoz{|}~ p!EFVw%þËx & )$ ¸Vß!ÖM 0?;<LnL L?yw ã Z$ %&N8_?G,âã WX³Y %&jWX³YÁcKB_?'Fß!ÖM 0?;<LnL? Ïyw?ÏG,ÄæE )2 %?#$89 2 (* :#() 2 D +! B#A4 %B *!2(/ 3 "<+89 #*!2E8:/9 FÖM 0 #G 8#9 *4#HB(B(%#IBJB+ #HBB(%#IBKB;
numnum 1 ·计数器加1 End If Loop Close #2 Print"字母出现的次数:";num End Sub 例7-2将C盘根目录下的一个文本文件old.dat复制到新文件new.dat中,并利用文件 操作语句将old.dat文件从磁盘上删除。 解答: (1)新建工程,在窗体上添加1个命令按钮。 (2)为命令按钮编写单击事件过程,打开旧文件,新建新文件,读旧文件内容,写入 新文件,删除旧文件,实现了文件的复制功能。 Private Sub Command1 Click() Dim strl As String Open "c:\old.dat"For Input As #1 Open "c:\new.dat"For Output As #2 Do While Not EOF(1) Input #1,strl Print #2,strl Loop Close #2,#1 Kill "C.\old.dat" End Sub 7.5练习与思考 习题71阅读下列程序,写出运行结果。程序如下: Dim a As Integer,,y As Integer‘在窗体的通用声明部分声明两个窗体级变量a和y Private Sub Form Load() Open "c:\al.dat"For Output As #1 Close #1 End Sub Private Sub Command14 Click() Open "c:\al.dat"For Append As #1 Call fa(5) y=y+a Print #1,"y=";y,"a=";a Close #1 End Sub Sub fa(i As Integer) X=1 Do Until x>i a=a+x X=X+3 Loop
2 2 @ F yw ã <%*4 ! / BEFVwB2 <%)2 m 5 /dM ² %% å7N C% !?Ïf ÆÇ %% ß//, Z$ %&N8_?G,âã WX³Y %&jWX³YÁcKB_?ÄÅ?N8N?01?ç N??'FAå^ )2 %?#$89 () +! B#A%%B *!2(/ +! B#A C%B +2!2(/ 3 "<+89 *!2/: /: ! /:/ LBA%%B <%)2 6 5 d_?E`a½ _nd$ (* :1(* MGAésxé Q 1 )2 ?%89 +! B#A%B +2!2(/ / <%)2 )2 %'?#$89 +! B#A%B (!! %(/ 4869 11@ /:B1B1:BB / <%)2 )248(* 9 GH @ @ !
End Sub 程序运行后,连续三次单击Commandl4,al.dat文件的最终结果? 习题7-2本题程序段的功能是,将顺序文本文件c:\text.txt的内容读入文本框txtTest中, 程序段如下,请在横线上填入必要的内容,使其完整。 Private Sub Command1 Click( Dim InputData As String *1 txtTest.Text="m 空1 Do While 空2 空3 txtTest.Text=txtTest.Text InputData Loop 空4 End Sub
<%)2 _`a[?Vc %'?% ½ 5 ²_¢^L?² #A 01ç² ; !? _¢nd?G,ç÷01?g\ð )2 %?#$89 *!2 () ; ; BB ??????? ???????????? 3 ??????? ?????????? ????????? ????????? ; ; ; ; N*!2 ! ??????? '???????? <%)2