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
| | |