ITEEDU

10.4 文件操作程序

有关目录和顺序文件的操作在第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