有关目录和顺序文件的操作在第8.3.6节中已有介绍和举例,本节主要介绍对记录文件的读写方法。记录文件是指文件中的每个分量是一个结构的文件,如:Fox系列数据库管理系统中的DBF文件,该文件除了文件头是由记录文件的整体信息和各字段描述信息之外,文件的主体内容就是由同一个结构组成的。
下面通过二个例子来介绍记录文件的读写方法。
例10.11 假设有一个简单的学生结构类型student,其包括:学号、姓名和年龄等信息,要求编写一个程序,该程序接受从键盘输入的学生记录信息,并把它们保存在文件students.dat之中。
| 解: | ||||
| .MODEL SMALL, C | ||||
| .486 | ||||
| student | STRUCT | |||
| id | DW ? | |||
| sname | DB 10 DUP(?) | |||
| age | DB ? | |||
| student | ENDS | |||
| .DATA | ||||
| fname | DB "Students.dat",0 | |||
| msg1 | DB "Id:$" | |||
| msg2 | DB "Name:$" | |||
| msg3 | DB "Age:$" | |||
| msg4 | DB "Continue?$" | |||
| msg5 | DB "Fail to create file$" | |||
| CRLF | DB 0AH, 0DH, "$" | |||
| buff | DB ?, ?, 11 DUP(?) | |||
| peason | STUDENT <> | |||
| .CODE | ||||
| DispMsg | PROC USES AX DX, Msg:PTR BYTE | ;显示字符串Msg | ||
| …… | ;参见例10.7 | |||
| DispMsg | ENDP | |||
| ;程序功能:把字符串Data转化成数值,不考虑负数。当遇到非法字符时,则结束转换操作; | ||||
| ;入口参数:Data为字符串的首地址,Len为该字符串的长度; | ||||
| ;出口参数:数值存放在AX中。 | ||||
| GetData | PROC USES BX CX SI, Len:BYTE, Data:PTR BYPE | |||
| XOR | CX, CX | |||
| MOV | CL, Len | |||
| MOV | SI, Data | |||
| XOR | AX, AX | |||
| XOR | BX, BX | |||
| .REPEAT | ||||
| MOV | BL, [SI] | |||
| SUB | BL, '0' | |||
| .BREAK .IF BL<0 || BL>9 | ;判断当前数值是否在0~9之间 | |||
| IMUL | AX, 10 | |||
| ADD | AX, BX | |||
| INC | SI | |||
| .UNTILCXZ | ||||
| RET | ||||
| GetData | ENDP | |||
| ;程序功能:读取指定长度的字符串,在输入前,显示有关输入内容的提示信息; | ||||
| ;入口参数:读入字符串的长度为Len,提示信息的首地址为MSG; | ||||
| ;出口参数:读入信息(字符串)存放缓冲区buff中。 | ||||
| GetInfo | PROC USES AX DX, Len:BYTE, Msg:PTR BYTE | |||
| INVOKE | DispMsg, Msg | ;显示提示信息 | ||
| MOV | AL, Len | |||
| MOV | buff, AL | |||
| MOV | AH, 0AH | |||
| LEA | DX, buff | |||
| INT | 21H | |||
| INVOKE | DispMsg, ADDR CRLF | ;显示回车、换行 | ||
| RET | ||||
| GetInfo | ENDP | |||
| .STARTUP | ||||
| MOV | AX, DS | |||
| MOV | ES, AX | |||
| LEA | DX, fname | |||
| MOV | CX, 20H | |||
| MOV | AH, 3CH | |||
| INT | 21H | ;创建文件 | ||
| .IF CARRY? | ;若创建失败,则显示失败信息 | |||
| INVOKE DispMsg, ADDR msg5 | ||||
| JMP over | ||||
| .ENDIF | ||||
| MOV | BX, AX | ;把句柄存入BX,为后面使用作准备 | ||
| again: | ||||
| INVOKE | DispMsg, ADDR CRLF | ;显示回车、换行 | ||
| INVOKE | GetInfo, 5, ADDR msg1 | ;读取学号(假定学号为4位整数) | ||
| INVOKE | GetData, 4, ADDR buff+2 | ;把学号字符串转化成数值 | ||
| MOV | peason.id, AX | ;把数值型学号存入学号字段 | ||
| INVOKE | GetInfo, 11, ADDR msg2 | ;读取姓名(假定姓名为10个字符) | ||
| MOV | CX, 10 | |||
| MOV | AL, ' ' | |||
| LEA | DI, peason.sname | |||
| REP | STOSB | ;先置姓名字段为10个空格 | ||
| MOV | CL, buff+1 | |||
| MOV | SI, OFFSET buff+2 | |||
| LEA | DI, peason.sname | |||
| REP | MOVSB | ;把输入的姓名存入姓名字段 | ||
| INVOKE | GetInfo, 3, ADDR msg3 | ;读取年龄(假定年龄为2位整数) | ||
| INVOKE | GetData, 2, ADDR buff+2 | ;把年龄字符串转化成数值 | ||
| MOV | peason.age, AL | ;把数值型年龄存入年龄字段 | ||
| MOV | CX, SIZE peason | |||
| LEA | DX, peason | |||
| MOV | AH, 40H | |||
| INT | 21H | ;把学生记录写入文件 | ||
| INVOKE | DispMsg, ADDR msg4 | ;提示是否继续输入 | ||
| MOV | AH, 1 | |||
| INT | 21H | |||
| AND | AL, 0DFH | |||
| CMP | AL, 'Y' | |||
| JZ | again | ;若按y或Y,则继续输入 | ||
| MOV | AH, 3EH | |||
| INT | 21H | |||
| over: | ||||
| .EXIT | 0 | |||
| END | ||||