第 8 章 数据文件
本章主要内容 第8章 数据文件 文件是指存放在外存储器(如磁盘)上的信息集合 使用文件可以将应用程序所处理的数据以文件的形式保存起来 程序文件和数据文件 本章主要内容 数据文件概述 顺序文件 随机文件 文件基本操作 文件系统对象(FSO)简介
8.1 数据文件概念 8.1.1 数据文件的结构 数据文件由记录组成,记录由字段组成,字段由字符组成 记录1 数据文件 记录2 ………… 8.1 数据文件概念 8.1.1 数据文件的结构 数据文件由记录组成,记录由字段组成,字段由字符组成 记录1 数据文件 记录2 ………… 学号 姓名 951001 张三 … 学号 姓名 951002 李四 … 字段
8.1.2 文件类型 (1)顺序文件:文本文件。文件中的记录按顺序一个接一个地排列。无法灵活地随意存取它。只适用于有规律的、不经常修改的数据 8.1.2 文件类型 (1)顺序文件:文本文件。文件中的记录按顺序一个接一个地排列。无法灵活地随意存取它。只适用于有规律的、不经常修改的数据 (2)随机文件:随机文件的每一个记录都有固定的长度,每一个记录都有记录号,这种文件的特点是允许用户存取文件中任一个记录。可以同时进行读或写操作存入和读出速度较快,数据容易更新 (3)二进制文件:可理解为长度为1的特殊的随机文件
8.1.3 文件处理的一般步骤 (1) 打开(或新建)文件 (2) 进行读、写操作 系统设置文件指针,用来记住当前读写的位置 8.1.3 文件处理的一般步骤 (1) 打开(或新建)文件 (2) 进行读、写操作 系统设置文件指针,用来记住当前读写的位置 (3) 关闭文件
8.1.4 文件的打开和关闭 1. 打开文件(Open) 示例: Open "d:\cj1.dat" For Output As #1 8.1.4 文件的打开和关闭 1. 打开文件(Open) Open 文件名 [For 模式][Access 存取类型][锁定] As [#]文件号[Len=记录长度] 说明:(1)文件名; (2) 模式用于指定文件访问的方式,包括: Append——从文件末尾添加 Binary——二进制文件 Input——顺序输入 Output——顺序输出 Random——随机存取方式 (3)文件号(或称文件缓冲区) (4)存取类型:访问文件的类型,为Read(只读)、Write(只写)、 Read Write(读写) (5)锁定:限制其他用户或其他进程对文件进行读写操作 Shared(共享)、Lock Read(禁止读)、Lock Write(禁止写)、 Lock Read Write(禁止读写) (6)Len:用来指定每个记录的长度(字节数) 示例: Open "d:\cj1.dat" For Output As #1
关闭文件的语句格式: Close [#] 文件号1 [,[#] 文件号2 …] ] 打开的文件使用完后必须关闭。 关闭文件的语句格式: Close [#] 文件号1 [,[#] 文件号2 …] ] 示例: Close #1
8.1.5 相关的语句和函数 1. FreeFile函数 格式:FreeFile 功能:返回一个在程序中没有使用的文件号 示例: FileNo=FreeFile Open "D:\MyFile.txt" For Output As FileNo 2. Seek语句和Seek函数 Seek函数的格式:Seek(文件号) 功能:返回文件指针的当前位置 对于随机文件,Seek函数返回指针当前所指的记录号。对于顺序文件,Seek函数返回指针所在的当前字节位置(从头算起的字节数) Seek语句的格式:Seek [#]文件号,位置 功能:将指定文件的文件指针设置在指定位置,以便进行下一次读或写操作 对于随机文件,“位置”是一个记录号;对于顺序文件,“位置”表示字节位置
3. Eof函数 格式:Eof(文件号) 功能:测试与文件号相关的文件是否已达到文件的结束位置。如果是,函数值为真值,否则为假值。 4. Lof函数 格式:Lof(文件名) 功能:返回与文件号相关的文件的总字节数 5.Loc函数 格式:Loc(文件号) 功能:返回与文件号相关的文件的当前读写位置
8.2 顺序文件 8.2.1 顺序文件的写入操作 以Output或Append方式打开文件,然后使用Write#语句或Print#语句将数据写入文件中 1. Write语句 格式:Write #文件号 [,表达式表] 功能:将表达式的值写到与文件号相关的顺序文件中 每个Write语句向顺序文件写入一个记录(不定长),它会自动地用逗号分开每个表达式的值。给字符串加上双引号 在最后一个字符写入后,插入一个回车换行符(Chr(13) + Chr(10)),以此作为记录结束的标记。 示例:Write #1, "Good Afternoon", 1998
例8.1 把1~50各数及能被7整除的数分别存入两个文件中 例8.1 把1~50各数及能被7整除的数分别存入两个文件中 把1~50的50个整数,以及这些数中能被7整除的数分别存入两个文件中,文件名为num1和num2,文件存放在VB缺省文件夹下 Private Sub Form_Load() Open "num1.txt" For Output As #1 Open "num2.txt" For Output As #2 For i = 1 To 50 Write #1, i If i Mod 7 = 0 Then Write #2, i Next i Close #1, #2 Unload Me End Sub 说明:num1.txt文件中一共写入50个记录,而num2.txt文件只写入其中能被7整除的若干个记录
例8.2 在num2.txt文件中加入51~200范围内能 被7整除的数 程序代码如下: Private Sub Form_Load() Open "num2.txt" For Append As #1 For i = 51 To 200 If i Mod 7 = 0 Then Write #1, i Next i Close #1 Unload Me End Sub
例8.3 建立学生成绩顺序文件Cj2.txt 设计步骤如下: (1)创建应用程序的用户界面和设置对象属性 输入某小组5名学生的成绩(表8.1),存放在“我的文档”(C:\My Documents)文件夹下的新建顺序文件Cj2.txt 设计步骤如下: (1)创建应用程序的用户界面和设置对象属性
Command1_Click():接收录入信息,并以一个记录存入文件中 Command2_Click():关闭文件和结束程序运行 (2) 设置事件过程 Form_Load():新建文件 Command1_Click():接收录入信息,并以一个记录存入文件中 Command2_Click():关闭文件和结束程序运行 Private Sub Form_Load() Open “C:\my documents\Cj2.txt“ For Output As #1 End Sub Private Sub Command1_Click() Dim num As String * 6, name As String * 8, score As Integer num = Text1.Text name = Text2.Text score = Val(Text3.Text) Write #1, num, name, score '存入记录 Text1.Text = "" '存完1个记录后清空 Text2.Text = "" Text3.Text = "" Text1.SetFocus '设置焦点
程序运行完成后,用Windows记事本来打开该顺序文件(文本文件),即可看到存入的文件内容 Private Sub Command2_Click() Close #1 End End Sub 程序运行完成后,用Windows记事本来打开该顺序文件(文本文件),即可看到存入的文件内容 说明:在显示的文件内容中,字符串(学号、姓名)两边的引号是系统自动加入的。字段之间通过逗号隔开
2. Print语句 格式:Print #文件号[,表达式表] 作用与Write一样。将一个或多个表达式的值写到与文件号相关的顺序文件中。其输出数据格式与Print方法在窗体上输出格式相似。 示例: Print #1, num, name, score ‘对应按区格式 Print #1, num;name;score ‘对应紧凑格式
8.2.2 顺序文件的读出操作 先用Input方式打开文件,然后采用Input或Line Input语句从文件中读出数据。通常,Input用来读出Write写入的记录内容,而Line Input用来读出Print写入的记录内容 1. Input语句 一般格式:Input #文件号,变量名表 功能:从指定文件中读出一个记录。变量个数和类型应该与要读取的记录所存储的数据一致。 打开文件时,文件指针指向文件中的第1个记录,以后每读取一个记录,指针就向前推进一次。如果要重新从文件的开头读数据,则先关闭文件后打开
例8.4 一个存取数据的示例 Show Open "data1.txt" For Output As #1 例8.4 一个存取数据的示例 程序代码如下: Private Sub Form_Load() Show Open "data1.txt" For Output As #1 a = 123 : b$ = "ABCD" Write #1, a, b$ '存入 Close #1 Open "data1.txt" For Input As #1 Input #1, c, d$ '读出 Print c, d$ End Sub 程序运行后,输出结果如下: 123 ABCD
例8.5 从文件“num2.txt”中读取数据 已知文件“num2.txt”中存放一批能被7整除的数(见例8.1及例8.2),现要求把这些数显示出来。每行显示4个数。 Private Sub Form_Load() Show k = 0 Open "num2.txt" For Input As #1 Do While Not EOF(1) '文件未结束时,循环 Input #1, x Print x, k = k + 1 If k Mod 4 = 0 Then Print '每显示4个数后换行 Loop Close #1 End Sub
例8.6 从文件Cj2.txt中读出5个学生的资料 (1) 创建应用程序的用户界面和设置对象属性
功能要求:单击“查询”按钮时,则打开文件后读取文件中所有记录内容,并显示在列表框List1中,计算得到的平均分显示在文本框Text1中 (2)编写程序代码 功能要求:单击“查询”按钮时,则打开文件后读取文件中所有记录内容,并显示在列表框List1中,计算得到的平均分显示在文本框Text1中 Private Sub Command1_Click() Dim n As String, m As String, s As Integer Dim x As String, t As Integer Open "C:\my documents\Cj2.txt" For Input As #1 t = 0 For i = 1 To 5 Input #1, n, m, s x = n + Space(2) + m + Str(s) List1.AddItem x :t = t + s Next i Close #1 Text1.Text = t / 5 End Sub
2. Line Input语句 格式:Line Input #文件号,字符型变量 功能:从打开的顺序文件中读出一个记录,即一行信息 例8.7 Print语句和Line Input语句配合使用的示例 Private Sub Form_Load() Show Open "mytxt.txt" For Output As #1 a = 123 : b$ = "ABCD" Print #1, a, b$ '写入第1个记录 Print #1, a; b$ '写入第2个记录 Close #1 Open "mytxt.txt" For Input As #1 Line Input #1, x$ '读出第1个记录 Print x$ Line Input #1, x$ '读出第2个记录 End Sub
3. Input函数 格式:Input(字符数,#文件号) 功能:从文件中读取指定字符数的字符 示例:A$ =Input(20, #1) 顺序文件的缺点是不能快速地存取所需的数据,也不容易进行数据的插入、删除和修改等工作,因此对于经常要修改数据或取出文件中个别数据,均不适合使用,但对于数据变化不大,每次使用时又需要从头往后顺序地进行读写,它还是不失为一种好的文件结构
8.3 随机文件 随机文件中每一个记录定长,并设置记录号,记录号从1开始。 8.3 随机文件 随机文件中每一个记录定长,并设置记录号,记录号从1开始。 存取记录时,只要说明所需记录的编号,系统就以此算出记录所在位置,然后加以写入或读出 8.3.1 初步认识 例8.8 建立一个随机文件,文件中包含10个记录,每个记录由一个数(1至10)的平方、立方和开方根三个数值组成,以该数作为记录号
(1) 通过Type...End Type语句定义记录类型,程序代码如下: Private Type Numval Squre As Integer Cube As Long Sqroot As Single End Type (2)利用某一过程(本例采用事件过程Form_Load)来完成该随机文件的存取操作,程序代码如下:
Dim nv As numval '定义一个numval类型的变量nv Private Sub Form_Load() '写入记录程序段 Private Sub Form_Load() Open "Data1.dat" For Random As #1 Len = Len(nv) For i = 1 To 10 nv.squre = i * i nv.cube = i * i * i nv.sqroot = Sqr(i) Put #1, i, nv Next i '读出记录程序段 Show For i = 2 To 10 Step 4 '只读出3个记录 Get #1, i, nv Print "第"; i; "号记录:", nv.squre, nv.cube, nv.sqroot Close #1 End Sub
运行结果: 第2号记录 4 8 1.414214 第6号记录 36 216 2.44949 第10号记录 100 1000 3.162278
进行随机文件存取操作,大致包括以下一些内容: (1) 在打开文件进行随机访问之前,使用Type…End Type语句定义一个记录类型(如Numval),该类型包括多个数据项,并与文件中记录应包括的域一致。 当通过Dim定义一个变量(如nv)为一个记录类型Numval时,该变量也就包含该类型的多个数据项,以后可通过nv.squre、nv.cube、nv.sqroot进行引用 (2) 指定Random类型打开文件,记录定长,打开文件后,就可以存或取任一个记录 (3)分别通过Get和Put语句,并指定记录号进行读一个记录或存一个记录 一定要建立好记录与记录号之间的关系
8.3.2 存取操作 1. 读语句 格式:Get #文件号[,记录号],变量 功能:从一个随机文件中读出指定记录到一个变量 2. 写语句 格式:Put #文件号[,记录号],变量 功能:把变量的值写入随机文件的记录中。 默认情况下,记录号编号为上一次使用的记录号加1
例8.9 建立职工工资随机文件 建立一个有5名职工工资信息的随机文件,其中包括职工的职工号(从001开始)、姓名及工资三种数据。采用职工号为记录号。设计步骤如下: (1) 在标准模块Module1中用Type语句定义一个职工工资记录类型 Type Salary Name As String*8 ‘定长字符串类型 Salary As Long End Type 不必把职工号作为记录的一个数据项存入文件 (2)利用事件过程Form_Load来进行文件处理
Private Sub Form_Load() Dim sal As salary Dim no As String * 3, recno As Integer Open "Data2.dat" For Random As #1 Len = Len(sal) For i = 1 To 5 s$ = "输入第" + Str(i) + "个职工的" no = InputBox(s$ + "编号") sal.name = InputBox(s$ + "姓名") sal.salary = Val(InputBox(s$ + "工资")) recno = Val(no) '记录号 Put #1, recno, sal '存入记录 Next i Close #1 End End Sub
例8.10 对职工工资信息进行查询、增、改、除等操作 (1)创建应用程序的用户界面 (2)设置对象属性
Public sal As salary, recno As Integer 'recno表示记录号 '检查编号的通用过程 (3)编写程序代码 ① 在标准模块Module1中定义记录类型和建立一个通用过程 Type salary name As String * 8 salary As Long End Type Public sal As salary, recno As Integer 'recno表示记录号 '检查编号的通用过程 Function Cheno(no As String) As Boolean recno = Val(no) If recno < 0 Or recno > 999 Then MsgBox "输入的职工号超出范围", 0, "检查编号" Cheno = True Else Cheno = False End If End Function
② 利用事件过程Form_Load()来打开文件和显示第一个记录 Private Sub Form_Load() Open "Data1.dat" For Random As #1 Len = Len(sal) Get #1, 1, sal Text1.Text = Format(1, "000") Text2.Text = sal.name Text3.Text = sal.salary End Sub
③ 编写“查询”按钮的Click事件过程 Private Sub Command1_Click() If Cheno(Text1.Text) Then Exit Sub If recno > LOF(1) / Len(sal) Then MsgBox "无此记录" Exit Sub End If Get #1, recno, sal Text2.Text = sal.name Text3.Text = Str(sal.salary) Text1.SetFocus '设置焦点 End Sub
Private Sub Command2_Click() If Cheno(Text1.Text) Then Exit Sub sal.name = Text2.Text sal.salary = Val(Text3.Text) Put #1, recno, sal Text1.SetFocus End Sub
⑤ 编写“清除”按钮的Click事件过程 Private Sub Command3_Click() If Cheno(Text1.Text) Then Exit Sub If recno > LOF(1) / Len(sal) Then MsgBox "无此记录" Exit Sub End If sal.name = "" '记录内容清空 sal.salary = 0 Text2.Text = "" '文本框清空 Text3.Text = "" Put #1, recno, sal Text1.SetFocus End Sub
Private Sub Command4_Click() Close #1 Unload Me End Sub
8.4 文件基本操作 可以在应用程序中很方便地对文件和文件夹进行操作 8.4 文件基本操作 可以在应用程序中很方便地对文件和文件夹进行操作 (1)建立文件夹语句(MrDir):MkDir [路径]文件夹名 示例:MkDir "D:\VB\Temp" (2)改变当前文件夹语句(ChDir):ChDir 路径 示例:ChDir "D:\VB\Dat" (3)删除文件夹语句(RmDir):RmDir [路径]文件夹名 示例:RmDir "D:\VB\Temp" (4)删除文件语句(Kill):Kill [路径]文件名 示例:Kill "D:\VB\datal.dat" Kill "D:\VB\dat\*.*"
(5)拷贝文件语句(FileCopy): FileCopy [路径1] 源文件 [, [路径2] 目标文件 ] 示例:FileCopy "C:\aaa.txt", "D:\Temp\bbb.txt" (6)文件的改名和移动: Name 原名 As 新名 改名示例:Name "C:\aaa.txt" As "C:\ccc.txt" 移动示例:Name "C:\Aaa.txt" As "C:\Tmp\Aaa.txt"
例8.11 文件操作示例 在“我的文档”(C:\My Documents)文件夹下创建一个新文件夹“mydir”,然后复制文件“C:\My Documents\cj2.txt”到新文件夹下,复制生成的文件名称由用户指定 Private Sub Form_Load() Show Print "正在进行文件操作" MkDir "c:\my documents\mydir" fname = InputBox("请输入新文件名", "更改文件名") fname = "c:\my documents\mydir\" + fname + ".txt" FileCopy "c:\my documents\cj2.txt", fname Print "已完成要求的操作" End Sub
(7)调用应用程序 格式:Shell(命令字符串[,窗口类型]) 功能:调用指定应用程序 示例: x = Shell("C:\Windows\Explorer.exe",1) 执行“C:\Windows”文件夹下的应用程序Explorer.exe, 并显示该程序窗口(例8.12)
8.5 文件系统对象(FSO) FSO (File System Object,文件系统对象方法) 但不支持二进制文件和随机文件的创建和操作 将逐渐淘汰传统的文件访问机制(即用Open等I/O语句及函数来实现对文件进行操作 )