8.1.3 随机读写文件
8.2 非缓冲文件系统
8.3 文件系统应用举例
[例8-8] 将输入的不同格式数据以字符串输入,然后将其转换进行文件的成块读写。
#include<stdio.h>
#include<stdlib.h>
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<stdio.h>
#include<stdlib.h>
#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<n;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<n;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<n;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<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<string.h>
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
Word教程网 | Excel教程网 | Dreamweaver教程网 | Fireworks教程网 | PPT教程网 | FLASH教程网 | PS教程网 |
HTML教程网 | DIV CSS教程网 | FLASH AS教程网 | ACCESS教程网 | SQL SERVER教程网 | C语言教程网 | JAVASCRIPT教程网 |
ASP教程网 | ASP.NET教程网 | CorelDraw教程网 |