Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103641605
  • 博文数量: 19283
  • 博客积分: 9968
  • 博客等级: 上将
  • 技术积分: 196062
  • 用 户 组: 普通用户
  • 注册时间: 2007-02-07 14:28
文章分类

全部博文(19283)

文章存档

2011年(1)

2009年(125)

2008年(19094)

2007年(63)

分类: C/C++

2008-04-17 16:46:05

  8.1.3 随机读写文件
8.2 非缓冲文件系统
8.3 文件系统应用举例
   


[例8-8] 将输入的不同格式数据以字符串输入,然后将其转换进行文件的成块读写。
#include
#include
main( )
{
    FILE *fp1;
    char *temp;
    int i;
    struct stu{ /*定义结构体类型*/
        char name[15]; /*姓名*/
        char num[6]; /* 学号*/
        float score[2]; /* 二科成绩*/
    }student;
    if((fp1=fopen("test.txt","wb"))==NULL) /* 打开文件*/
    {
        printf("cannot open file");
        exit(0);
    }
    for( i=0;i<2;i++) 
    {
        printf("input name:");
        gets(student.name); /*输入姓名*/
        printf("input num:");
        gets(student.num); /* 输入学号*/
        printf("input score1:");
        gets(temp); /*输入成绩*/
        student.score[0]=atof(temp);
        printf("input score2:");
        gets(temp);
        student.score[1]=atof(temp);
        fwrite(&student,sizeof(student),1,fp1); /*成块写入到文件*/
    }
    fclose(fp1);
    if((fp1=fopen("test.txt","rb"))==NULL)
    {
        printf("cannot open file");
        exit(0);
    }
    printf("---------------------\n");
    printf("%-15s%-7s%-7s%-7s\n","name","num","score1","score2");
    printf("---------------------\n");
    for (i=0;i<2;i++)
    {
        fread(&student,sizeof(student),1,fp1);
        printf("%-15s%-7s%7.2f%7.2f\n",student.name,student.num,student.score[0],student.score[1]);
    }
    fclose(fp1);
}
运行程序如下:
input name:li-ying
input num: j0123
input score1:98.65
input score2:89.6
input name:li-li
input num: j0124
input score1:68.65
input score2:86.6
----------------------------------------
name      num    score1    score2
----------------------------------------
li-ying  j0123     98.65    89.60
li-li    j124      68.64    86.60

8.1.3 随机读写文件
    随机对文件的读写是指在文件内部任意对文件内容进行访问,这也就需要对文件进行详细的定位,只有定位准确,才有可能对文件随机访问。
    C语言提供了用于文件定位的函数,它的作用是使文件指针移动到所需要的位置。
    int fseek(FILE *fp,long d,int pos)
fp是文件指针,d是位移量, pos是起始点。
Pos的取值为:
0 :文件开始处
1 :文件的当前位置
2 :文件的尾部
    位移量d是long型的数据,可以为正或负值。表示从起始点向下或向上的指针移动。函数的返回值若操作成功为0,操作失败为非零。
例如:fseek(fp,5L,0);将文件指针从文件头向下移动5个字节。
fseek(fp,-10L,2);将文件指针从当前位置向上移动10个字节。
rewind() 将文件指针移动到文件头。
ftell(FILE *fp) 返回文件指针的当前位置。

[例8-9] 写入5个学生记录,记录内容为学生姓名、学号、两科成绩。写入成功后,随机读取第三条记录,并用第二条记录替换。
#include
#include
#define n 5
main( )
{
    FILE *fp1; /*定义文件指针*/
    char *temp;
    int i,j;
    struct stu{ /* 定义学生记录结构*/
        char name[15];
        char num[6];
        float score[2];
    }student[n];
    if ((fp1=fopen("test.txt","wb"))==NULL) /*以二进制只写方式打开文件*/
    {
        printf("cannot open file");
        exit(0);
    }
    for( i=0;i    {
        printf("input name:"); /*输入姓名*/
        gets(student[i].name);
        printf("input num:");
        gets(student[i].num); /*输入学号*/
        printf("input score1:");
        gets(temp); /*输入一科成绩*/
        student[i].score[0]=atof(temp);
        printf("input score2:");
        gets(temp); /* 输入第二科成绩*/
        student[i].score[1]=atof(temp);
        fwrite(&student[i],sizeof(struct stu),1,fp1); /* 成块写入*/
    }
    fclose(fp1); /*关闭* /
    if((fp1=fopen("test.txt","rb+"))==NULL)
    { /*以可读写方式打开文件* /
        printf("cannot open file");
        exit(0);
    }
    printf("---------------------\n");
    printf("%-15s%-7s%-7s%-7s\n","name","num","score1","score2");
    printf("---------------------\n");
    for (i=0;i    { /*显示全部文件内容*/
        fread(&student[i],sizeof(struct stu),1,fp1);
        printf("%-15s%-7s%7.2f%7.2f\n",student[i].name,student[i].num,student[i].score[0],student[i].score[1]);
    }
    /*以下进行文件的随机读写*/
    fseek(fp1,3*sizeof(struct stu),0); /* 定位文件指针指向第三条记录*/
    fwrite(&student[1],sizeof(struct stu),1,fp1);
    /* 在第三条记录处写入第二条记录*/
    rewind(fp1); /*移动文件指针到文件头* /
    printf("---------------------\n");
    printf("%-15s%-7s%-7s%-7s\n","name","num","score1","score2");
    printf("---------------------\n");
    for (i=0;i    { /*重新输出文件内容*/
    fread(&student[i],sizeof(struct stu),1,fp1);
    printf("%-15s%-7s%7.2f%7.2f\n",student[i].name,student[i].num,student[i].score[0],student[i].score[1]);
    }
    fclose(fp1); /*关闭文件*/
}
运行程序:
input name:li-ying
input num: j0123
input score1:98.65
input score2:89.6
input name:li-li
input num: j0124
input score1:68.65
input score2:86.6
input name:li-ping
input num: j0125
input score1:88.5
input score2:84.6
input name:Wang-xian
input num: j0126
input score1:98
input score2:94
input name:Ma-ling
input num: j0127
input score1:66.5
input score2:80.6
--------------------------------------
name      num       score1    score2
--------------------------------------
li-ying   j0123      98.65     89.60
li-li     j0124       68.64     86.60
li-ping   j0125       88.50     84.60
Wang-xian j0126       98.00     94.00
Ma-ling   j0127       66.50     80.60
--------------------------------------
name      num        score1    score2
--------------------------------------
li-ying   j0123      98.65      89.60
li-li     j0124      68.64      86.60
li-li     j0124     68.64     86.60
Wang-xian j0126      98.00      94.00
Ma-ling   j0127      66.50      80.60
    程序的第二次输出,即随机访问后,文件中会有两条相同的记录。

8.2 非缓冲文件系统
   
前面介绍的缓冲文件系统是借助文件结构体指针来对文件进行管理,通过文件指针来对文件进行访问,既可以读写字符、字符串、格式化数据,也可以读写二进制数据。非缓冲文件系统依赖于操作系统,通过操作系统的功能对文件进行读写,是系统级的输入输出,它不设文件结构体指针,只能读写二进制文件,但效率高、速度快,由于ANSI标准不再包括非缓冲文件系统,因此建议大家最好不要选择它。本书只作简单介绍。

1. 文件的打开与关闭

非缓冲文件系统不是ANSI标准定义的,是UNIX型I/O系统的一员,所以,其原型位于io.h文件中。
打开文件:
int open(char *fname,int access);
打开文件名为fname,以access方式访问:
access的值为:O_RDONLY 只读
O_WRONLY 只写
O_RDWR 读写
关闭文件:
close(int fd);

下述程序用UNIX系统打开和关闭一个文件:
#include "io.h"
#include "fcntl.h"
#include "sys\stat.h"
main(argc, argv)
int argc;
char *argv[]
{
    int fd;
    if((fd=open(argv[1],O_RDONLY))==-1) /* 以只读方式打开文件*/
    {
        printf("cannt open file!");
        exit(0);
    }
    printf("file existent!");
    if(close(fd)) printf("error in closing file\n");
}

2. 文件的读写
    对非缓冲文件系统的读写函数的原型在io.h头文件中,其调用形式为:
    int read(int fd,void *buf,int count)
    read( )函数从fd说明的文件中读取count个字节到buf所指向的缓冲区。函数的返回值是实际读写的字节数。
    int write(int fd,void *buf,int count)
    write( )函数把count个字节从buf写入到fd说明的文件中。函数的返回值是实际写入的字节数。

    下面例子从文件TEST.TST中读取它的前半100个字节并放到数组buffer中。
#include "io.h"
#include "stdio.h"
#include "fcntl.h"
main( )
{
    int fd;
    char buffer[100];
    if ((fd=open("TEST.TST",O_RDONLY))==-1) /* 打开文件* /
    {
        printf("cannot open file !\n");
        exit(0);
    }
    if(read(fd,buffer,100)!=100) /*判断读写的字节数是否正确*/
    printf("Possible read error.");
}

8.3 文件系统应用举例
    文件操作在程序设计中是非常重要的技术,文件的数据格式不同,决定了对文件操作方式的不同。

[例8-10] 我们需要同时处理三个文件。文件addr.txt记录了某些人的姓名和地址;文件tel.txt记录了顺序不同的上述人的姓名与电话号码。希望通过对比两个文件,将同一人的姓名、地址和电话号码记录到第三个文件addrtel.txt。首先看一下前两个文件的内容:
type         addr.txt
hejie        tianjing
liying       shanghai
liming       chengdu
wangpin      chongqing

type         tel.txt
liying        12345
hejie         8764
wangpin       87643
liming        7654322
    这两个文件格式基本一致,姓名字段占14个字符,家庭住址或电话号码长度不超过14个字符,并以回车结束。文件结束的最后一行只有回车符,也可以说是长度为0的串。在两个文件中,由于存放的是同一批人的资料,则文件的记录数是相等的,但存放顺序不同。我们可以任一文件记录为基准,在另一文件中顺序查找相同姓名的记录,若找到,则合并记录存入第三个文件,将查找文件的指针移到文件头,以备下一次顺序查找。
#include
#include
#include
#include
main( )
{
    FILE *fptr1,*fptr2,*fptr3; /* 定义文件指针*/
    char temp[15],temp1[15],temp2[15];
    if ((fptr1=fopen("addr.txt","r"))==NULL)/*打开文件*/
    {
        printf("cannot open file");
        exit(0);
    }
    if((fptr2=fopen("tel.txt","r"))==NULL)
    {
        printf("cannot open file");
        exit(0);
    }
    if((fptr3=fopen("addrtel.txt","w"))==NULL)
    {
        printf("cannot open file");
        exit(0);
    }
    clrscr(); /*清屏幕*/
    while(strlen(fgets(temp1,15,fptr1))>1) /* 读回的姓名字段长度大于1 */
    {
        fgets(temp2,15,fptr1); /* 读地址*/
        fputs(temp1, fptr3); /* 写入姓名到合并文件*/
        fputs(temp2, fptr3); /* 写入地址到合并文件*/
        strcpy(temp, temp1); /* 保存姓名字段*/
        do /*查找姓名相同的记录*/
        {
            fgets(temp1, 15, fptr2);
            fgets(temp2, 15, fptr2);
        }while(strcmp(temp,temp1)!=0);
        rewind(fptr2); /* 将文件指针移到文件头,以备下次查找*/
        fputs(temp2, fptr3); /* 将电话号码写入合并文件*/
    }
    fclose(fptr1); /*关闭文件*/
    fclose(fptr2);
    fclose(fptr3);
}

    程序运行后,我们来看一下合并后的文件addrtel.txt的内容:
type           addrtel.txt
hejie          tianjing
8764
liying          shanghai
12345
liming          chengdu
7654322
wangpin         chongqing
87643

阅读(167) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~