Qbasic 教程 

第十章   文件

文件——程序或数据存放在磁盘上的形式,存放在外部介质上的数据的集合;

程序——文件

数据 ——文件

一、文件的概念

1、分类

1)从文件的内容区分;

  • 程序文件——源程序或可执行的目标程序
  • 数据文件——输入/输出数据;
2)从文件的存储形式区分;
  • ASCⅡ文件(文本文件)


    源程序、字符串数据可用TYPE命令显示;

    存储时需转换ASCⅡ——二进制形式;

  • 二进制文件
      用二进制形式存储
(3)从文件的组织形式区分;
  • 顺序文件(不定长)
  • 随机文件(定长)
2、文件与记录
    一个文件是由若干个记录组成,一个记录包含若干个数据项。
例如一个学生的数据:学号、姓名、年龄、成绩等可看成一组数据组成一个记录;

3、文件名

    扩展名:.BAS、.FOR、.PAS、.C
4、文件的读写和文件缓冲区
    读文件——将文件读入内存,或将文件读入计算机。
    写文件——从计算机主机向磁盘传送(输出)数据。
    对磁盘上的数据文件进行读写操作时,必须在内存中开辟一个“文件缓冲区”,以建立必要的输入/输出通道。
5、文件指针
    每文件都有一个指针,指向当前应读写的位置,从文件中读数据,就是读指针所指向位置处的数据。向文件写数据,是写到指针所指向的位置处。
二、顺序文件

1、概念

    顺序存取文件(SEQIEMCE ACCESS FILE
——文件中各记录写入顺序,存放的顺序和读出的顺序三者是一致的。
 
 
 
记录1 
…… 
记录i 
…… 
记录n 
 

2、顺序文件的打开与关闭

使用之前,先“打开”文件,使用后“关闭”它;

    (1).OPEN 语句
格式OPEN <文件名> FOR <读写方式> AS#<文件号>

<读写方式>:

  • OUTPUT:写数据,向文件输出;
  • INPUT:读数据,从文件读入;
  • APPEND:写数据:添加记录;
<文件号>:即文件缓冲区号,一个文件都要指定一个不同的文件号(1~225);

说明

  • OUTPUT方式打开文件,建立新文件,指针指向首记录;将删除已存在的文件。
  • 以INPUT方式打开已存在的文件,指针指向首记录;
  • 以APPEND方式打开文件,指针指向文件尾;可建立新文件
2CLOSE语句
    关闭已用的文件
CLOSE [#<文件号1>][,#<文件号2>]……

关闭由文件号指定的文件缓冲区,将内容存盘,如不指定文件号,则关闭所有已打开的文件;

3、输出数据(写文件)

    新文件写入记录
(1)PRINT#语句
    格式PRINT #<文件号><输出项>

    例;PRINT #1a;b;c

    注意:逗号与分号的差别,与PRINT语句类似在对字符串存盘时,注意引入定界符。

(2)WRITE#语句
存盘时,各数据间插入逗号,并给字串加双引号,且正数前面不设空格。

例:

    OPEN "student.dat" FOR OUTPUT AS #1
    READ num,nam$,sex$,score
    DO UNTIL nam$="end"

      WRITE #1,num,nam$,sex$,score
      READ num,nam$,sex$,score
    LOOP
    DATA 101,Li,m,90,103,Wang,f,98
    DATA 104,Xiu,f,100,105,Zhang,m,78
    DATA 107,Tan,m,99,109,Ling,f,88
    DATA 000,end,,
    END
说明:(1)、文件中的记录以:“回车换行符”相隔:
     CHR$(13)、CHR$(10)

(2)、文件最后用“文件结束符”结束CHR$(26)

一个记录的长度不能超过225个字符;
(3)、PRINT#与WRITE#的区别:

  • WRITE#语句(数据项之间用“,”或“;”均相同)
      101,"Li","m",90
      103,"Wang","f",98
  • PRINT#语句(数据项之间用“;”)
      101 Lim 90
      103 Wangf 98
  • PRINT#语句(数据项之间用“,”)
      101       Li        m         90
      103       Wang      f         98
4、输入数据(读文件)

从已建立文件中读入数据到计算机中;

    (1)INPUT#语句
    格式INPUT #<文件号><变量1>[<变量2>…..]
    每次从文件中读出一个记录,
    注意:变量类型应与数据一致;
例:

    OPEN "student.dat" FOR OUTPUT AS #3
    DO

      INPUT #3,num,nam$,sex$,score
      PRINT num,nam$,sex$,score
    LOOP UNTIL EOF(3)
    CLOSE
    END
    终止函数

    EOF<文件号>
     

      检查记录指针是否指向文件尾,是则真(-1),否则为假(0
    (2)LINE INPUT#语句
格式LINE INPUT#<文件号><字串变量>
    将文件的记录,以字符形式读入;
例:

    OPEN "student.dat" FOR OUTPUT AS #3
    DO

      LINE INPUT #3,stud$
      PRINT stud$
    LOOP UNTIL EOF(3)
    CLOSE
    END
5、文件的修改

    若要修改已有的顺序文件,则要利用中间文件,因为对一个顺序文件不能既读又写。对顺序文件的修改步骤:
(1)、用INPUT方式打开需要修改的旧文件,准备从中逐个读出数据;
(2)、另设一个中间临时文件(用OUTPUT方式打开),用来存放修改后的各记录;
(3)、逐个读入旧文件的记录,用户决定是否修改?如果不改,就把此记录原封不动地写到中间文件中去;如果要修改,则在修改后再写到中间文件中。
(4)、将旧文件删除,把中间文件改名为原来的旧文件的名称。

:

    OPEN "student.dat" FOR INPUT AS #1
    OPEN "temp" FOR OUTPUT AS #2
    DO UNTIL EOF(1)

      INPUT #1,num,nam$,sex$,score
      PRINT num,nam$,sex$,score
      INPUT "chang?(y/n)";r$
      if UCASE$(r$)="Y" THEN INPUT num,nam$,sex$,score
      WRITE #2,num,nam$,sex$,score
      INPUT "insert?(y/n)";q$
      if UCASE$(q$)="Y" THEN
        INPUT num,nam$,sex$,score
        WRITE #2,num,nam$,sex$,score
      END IF
    LOOP
    CLOSE
    KILL "student.dat"
    NAME "temp" AS "student.dat"
    END
6、有关函数和语句
  • EOF()函数


    尾测试

  • INPUT$()函数


    格式:INPUT$<字节数><文件号>)

    从指定的打开文件中读取指定数目的字符;

  • LOF()函数


    给出指定文件已进行读写的字节数;
    格式:LOF<文件号>

  • SEEK()函数


    格式:SEEK(<文件号>)

    给出指定文件的当前指针

  • SEEK语句


    指针移动

    格式:SEEK#<文件号>,<字节位置>

    有关顺序文件的语句和函数:P33612.7
     

三、随机文件(RAMDOM ACCESS FILE)
    随机存取文件——所有记录等长,各记录相应的数据项的长度也相同;

    按记录号进行存取,记录的顺序不一致,可直接读写任一条记录。

    1、随机文件的建立

    1OPEN <文件名> AS#<文件号> [LEN=<长度>]

    存取方式不用指定,自动加上“FOR RANDOM”,表示随机文件;

    2)定义缓冲区中各“域”的长度(FIELD 字段)
     

      FIELD <文件名><域宽>AS<域名>[<域宽>AS <或名>]
    定义记录的结构

    如:FIELD #1, 10 AS A$, 15AS B$, 36AS C$

    3)随机文件的记录中各域只能存放字符串数据,在对数值型数据进行处理时,要经过转换;
    (4)数值转换为字符的函数

    MKI$<整型表达式> 2字节

    MKS$<单精度表达式> 4字节

    MKD$<双精度表达式> 8字节

    称为“内码字符串”
    (5)缓冲区中各域的字符串变量赋值

    LSET <域变量>=<字符串>(左对齐)

    RSET <域变量>=<字符串>(右对齐)
    (6)将文件缓冲区中的数据存盘

    PUT #<文件号>[<记录号>]
    (7)用CLOSE关闭文件

:

    OPEN "good.dat" FOR RANDOM AS #1 LEN=23
    FIELD #1, 2 AS n$,15 AS m$,4 AS P$,2 AS s$
    DO

      READ num%,nam$,price,stock%
      IF num%=9999 THEN EXIT DO
      LSET n$=MKI$(num%)
      LSET m$=nam$
      LSET p$=MKS$(price)
      LSET s$=MKI$(stock%)
      PUT #1
    LOOP
    DATA .............
    DATA .............
    DATA .............
    DATA .............
    DATA .............
    DATA 9999,,,
    CLOSE
    END
    2、随机文件的读入
(1)、打开随机文件
     OPEN <文件名> AS#<文件号> [LEN=<长度>]
(2)、定义文件缓冲区中各域的长度;
FIELD <文件名><域宽>AS<域名>[<域宽>AS <或名>]
(3)、从指定的文件中读取一个记录
    GET #<文件号> [<记录号>]
(4)、将内码字符串还原为数值型数据;
    CVI<2个字节的域变量>)——整数
    CVS(<4个字节的域变量>)——单精度
    CVD(<8个字节的域变量>)——双精度
    这三个函数是MKI$MKS$ MKD$的逆运算
(5)、关闭文件

     CLOSE

:

    OPEN "good.dat" FOR RANDOM AS #1 LEN=23
    FIELD #1, 2 AS n$,15 AS m$,4 AS P$,2 AS s$
    PRINT "num","name","price","stock"
    FOR i%=1 TO LOF(1)/23
      GET #1,i%
      num%=CVI(n$)
      nam$=m$
      price=CVS(p$)
      stock%=CVI(s$)
      PRINT num%,nam$,price,stock%
    NEXT i%
    CLOSE
    END

    3、随机文件的修改

    随机文件的优点:可直接读写任何一个记录,且既能读又能写。

:
    OPEN "good.dat" FOR RANDOM AS #1 LEN=23
    FIELD #1, 2 AS n$,15 AS m$,4 AS P$,2 AS s$
    INPUT "which record:";r
    DO UNTIL r=0
      GET #1,r
      num%=CVI(n$)
      nam$=m$
      price=CVS(p$)
      stock%=CVI(s$)
      PRINT num%,nam$,price,stock%
      INPUT "price=";price
      LSET p$=MKS$(price)
      PUT #1,r
      INPUT "which record:";r
    LOOP
    CLOSE
    END

    3、记录型变量

    一个记录包括若干个“域”,在同一文件中各个记录所包含的域都是相同的,这样可以定义一种新的变量类型——记录。
     
    1001 Shirt 67 120
    1002 Skirt 87 108
    1003 Coat 231.5 67
    (1)、定义记录类型

    格式:TYPE  <记录类型名>

          <域名1> AS <类型>
          <域名2> AS <类型>
          ......
          <域名n> AS <类型>
        END TYPE
    例如: TYPE goods
          num    AS  INTEGER
          nam    AS  STRING*15
          price  AS  SINGLE
          stock  AS  INTEGER
          TYPE END
         
     (2)、定义记录变量

    格式: DIM <记录变量名> AS <记录类型名>

    例如:  DIM  a  AS goods

    (3)、记录变量中的域表示法

    格式: <记录变量名>.<域名>

    例如:  a.num     表示a变量中的num域。

    4、用于记录变量的读写语句

    (1)、GET#语句
    格式:GET #<文件号> [,<记录号>][,<记录变量>]
    功能: 用于从文件中读一个指定的记录,赋给一个记录变量。
    (2)、PUT#语句
    格式:PUT #<文件号> [,<记录号>][,<记录变量>]
    功能: 将一个记录变量的内容写到指定的记录中去。

例10-8:用记录变量的方法建立一个随机文件。
(P346例12.14)
    TYPE goods
      num    AS  INTEGER
      nam    AS  STRING*15
      price  AS  SINGLE
      stock  AS  INTEGER
    TYPE END
    DIM cloth  AS  goods
    OPEN "good.dat" FOR RANDOM AS #1 LEN=LEN(cloth)
    DO
    READ cloth.num,cloth.nam,cloth.price,cloth.stock
    IF cloth.num=9999 THEN EXIT DO
    PUT #1,,cloth
    LOOP
    DATA .....
    .....
    DATA 9999,,,
    CLOSE
    END
例:用记录变量的方法读入一个随机文件内容。

    TYPE goods
      num    AS  INTEGER
      nam    AS  STRING*15
      price  AS  SINGLE
      stock  AS  INTEGER
    TYPE END
    DIM cloth  AS  goods
    OPEN "good.dat" FOR RANDOM AS #1 LEN=LEN(cloth)
    PRINT "num","name","price","stock"
    FOR i%=1 TO LOF(1)/LEN(cloth)
      GET #1,i%,cloth
    PRINT cloth.num,cloth.nam,cloth.price,cloth.stock
    NEXT i%
    CLOSE
    END

例:用记录变量的方法修改一个随机文件内容。

    TYPE goods
      num    AS  INTEGER
      nam    AS  STRING*15
      price  AS  SINGLE
      stock  AS  INTEGER
    TYPE END
    DIM cloth  AS  goods
    OPEN "good.dat" FOR RANDOM AS #1 LEN=LEN(cloth)
    DO
      INPUT "which record";r
      IF r=0 THEN EXIT DO
      GET #1,r,cloth
    PRINT cloth.num,cloth.nam,cloth.price,cloth.stock
    INPUT "price=";cloth.price
    PUT #1,r,cloth
    LOOP
    CLOSE
    END

四、文件与目录处理
    1、显示磁盘目录
       FILES ["文件名"]

    例:FILES "*.BAS" —显示当前目录下,扩展名为BAS的所有文件;

    2、执行DOS命令
       SHELL [命令字符串]

    例:SHELL "dir"  — 暂时退出QBASIC,执行DOS的命令dir(显示目录),然后返回QBASIC。
    注:如果没有[命令字符串],则转到DOS命令状态,可用EXIT返回QBASIC。

    3、文件改名
       NAME <旧名> AS <新名>
    可改名或修改文件路径。

    4、文件删除
        KILL <文件名>

    5、目录操作
    MKDIR <路径名>——建立子目录
    CHDIR <路径名>——改变当前目录
    RMDIR <路径名>——删除(空)目录