文件的基本概述
1、二进制文件和ASCII码文件
ASCII文件(文本文件):每一个字节放一个ASCII代码
二进制文件:数据按其在内存中的存储形式原样输出到磁盘上存放
ASCII文件和二进制文件的比较:ASCII文件便于对字符进行逐个处理,也便于输出字符。但一般占存储空间较多,而且要花费转换时间。二进制文件可以节省外存空间和转换时间,但一个字节并不对应一个字符,不能直接输出字符形式。
一般中间结果数据需要暂时保存在外存上,以后又需要输入内存的,常用二进制文件保存。
2、C语言对文件处理的方法
文件类型指针
文件信息有系统定义的名为 FILE 的结构体描述
FILE *fp;
fp是指向FILE类型结构体的指针变量,可以用fp指向某一文件的结构体变量从而通过该指针访问文件
文本文件操作
1、文件打开函数——fopen
FILE *fp;
fp=fopen(文件名,打开方式);
返回值:成功返回指针,失败返回NULL
2、文件关闭函数——fclose
fclose(文件指针);
功能:使文件指针与文件脱钩,不在相互联系,无法在用该指针对该文件进行操作
返回值:成功返回0,失败返回EOF(-1)
3、字符读写函数——fputc / fgetc
ch=fgetc(fp);
功能:从指定文件中读出一个字符,该文件必须以读或读写的方式打开
返回值:成功读取字符赋值给ch,遇到结束符则返回EOF
fputc(ch,fp);
功能:将字符写入fp所指向的文件中
返回值:成功返回值就是输出的字符,失败的返回值就是EOF
下面给出几个例子
建立一个文件,并输入一些内容
void main(int argc, char* argv[])
{
FILE *fp;
char ch,filename[10];
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL)
{ printf("cannot open file\n");exit(0); }
ch=getchar( );
ch=getchar( );
while(ch!='#')
{
fputc(ch,fp);
putchar(ch);
ch=getchar();
}
fclose(fp);
}
将以上建立的文件内容进行输出
void main(int argc, char* argv[])
{
FILE *fp;
char ;
if((fp=fopen(filename,"w"))==NULL)
{ printf("cannot open file\n");exit(0); }
while(!feof(fp))
{
ch=fgetc(fp);
putchar(ch);
}
fclose(fp);
}
二进制文件操作
数据块读写 (fread、fwrite)函数
函数调用:
fread (buffer,size,n,fp);
fwrite(buffer,size,n,fp);
参数说明:
buffer:是一个指针。对fread 来说,它是读入数据的存放地址。对fwrite来说,是要输出数据的地址(均指起始地址)。
size:要读写的字节数。
n:要进行读写多少个size字节的数据项。
fp:文件型指针。
例子:将四个学生的的数据的输入和输出
#include <stdio.h>
#define SIZE 4
struct student
{
char name[8];
int num;
} stud[SIZE];
void save( )
{
FILE *fp;
int i;
if((fp=fopen("d:\\student","wb"))==NULL)
{
printf("cannot open file\n");
exit(0);
}
for(i=0; i<SIZE; i++) /*二进制写*/
if(fwrite(&stud[i],sizeof(struct student),1,fp)!=1)
printf("file write error\n");/*出错处理*/
fclose(fp);
} /*关闭文件*/
void main(int argc, char* argv[])
{
int i;
for(i=0; i<SIZE; i++) /*从键盘读入学生信息*/
scanf("%s%d",stud[i].name,&stud[i].num);
save( ); /*保存学生信息*/
}
例子:将以上文件进行输出
void list( )
{
FILE *fp;
int i;
if((fp=fopen("d:\\student","rb"))==NULL)
{
printf("cannot open file\n");
exit(0);
}
for(i=0; i<SIZE; i++) /*读学生信息*/
if(fread(&stud[i],sizeof(struct student),1,fp)!=1)
printf("file write error\n");/*出错处理*/
for(i=0; i<SIZE; i++) /*显示学生信息*/
printf("%s%d\n",stud[i].name,stud[i].num);
fclose(fp); /*关闭文件*/
}
void main(int argc, char* argv[])
{
list( );
}
文件的定位
1、顺序读写和随机读写
顺序读写:位置指针按字节位置顺序移动。
随机读写:读写完上一个字符(字节)后,并不一定要读写其后续的字符(字节),而可以读些文件中任意位置上所需要的字符(字节)。
2、rewind函数
函数作用:使位置指针重新返回文件的开头,无返回值
例子:有一个磁盘文件,首先将它的内容显示在屏幕上,然后把它复制到另一文件上
#include<stdio.h>
main()
{
FILE *fp1,*fp2;
fp1=fopen("file1.c","r");
fp2=fopen("file2.c","w");
while(!feof(fp1))
putchar(fgetc(fp1));
rewind(fp1);
while(!feof(fp1))
fputc(fgetc(fp1),fp2);
fclose(fp1);
fclose(fp2);
}
3、fseek函数(一般用于二进制文件)
函数功能:改变文件的位置指针
函数调用形式:fseek(文件类型指针,位移量,起始点)
起始点:
文件开头 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾 SEEK_END 2
位移量:以起始点为基点,向前移动的字节数。一般要求为long型
fseek函数应用举例
fseek(fp,100L,0);//将位置指针移到离文件头100个字节处
fseek(fp,50L,1);//将位置指针移到离当前位置50个字节处
fseek(fp,50L,2);//将位置指针从文件末尾处向后退10个字节
练习题
本题注意fgets函数的用法,可一次读取一行
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char s[50];
if((fp=fopen("g:\\data.in","r+"))==NULL)
{
printf("can't open file\n");
exit(0);
}
int i;
while(fgets(s,50,fp)!=NULL)//多行读取,每次可以读取一行,如果遇到结尾返回NULL
{
for(i=0; i<strlen(s); i++) //这两种终止循环的方法均可,但是我个人感觉文件中第二个比较好用
{
if(s[i]>='A'&&s[i]<='Z')//将大写内容变为小写
{
s[i]=(s[i]-'A')+'a';
}
}
printf("%s",s);
}
fclose(fp);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp,*read;
char s[305];
int i,n,l,num;
if((fp=fopen("text01.txt","w"))==NULL)//将键盘内容输入文件text01.txt
{
printf("can't open file\n");
exit(1);
}
if((read=fopen("text01.txt","r"))==NULL)//将文件text01.txt读出并且输出到屏幕
{
printf("can't open file\n");
exit(1);
}
while(scanf("%d ",&n)!=EOF)//此处输入注意吃掉数字后面的空格,否则n的值不会更新
{
if(n==0){break;}
for(i=0;i<n;i++)
{
gets(s);
l=strlen(s);
fprintf(fp,"%d ",l);
fputs(s,fp);
fputc('\n',fp);
memset(s,0,sizeof(s));
}
}
rewind(fp);//将文件指针指向文件头
while(fscanf(read,"%d ",&num)!=EOF)
{
fgets(s,num,read);
for(i=0;s[i]!='\0';i++)//因为fgets会保留结尾的换行符,所以用s[i]!='\0'来终止输出
{
putchar(s[i]);//此处如果用puts直接输出,puts会直接把'\0'变为'\n',输出会多一个\n;
}
}
fclose(fp);
fclose(read);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
struct stu
{
int num;
char name[21],sex;
double score[3];
double avg,sum;
};
int main()
{
FILE *fp;
int n,i,l;
struct stu *s;
if((fp=fopen("g:\\student.txt","w"))==NULL)
{
printf("can't open file!\n");
exit(1);
}
scanf("%d",&n);
s=(struct stu *)malloc(n*sizeof(struct stu));
for(i=0; i<n; i++)
{
scanf("%d",&s[i].num);
getchar();
gets(s[i].name);
scanf(" %c ",&s[i].sex);
scanf("%lf%lf%lf",&s[i].score[0],&s[i].score[1],&s[i].score[2]);
s[i].sum=s[i].score[0]+s[i].score[1]+s[i].score[2];
s[i].avg=s[i].sum/3.0;
fprintf(fp,"%d ",s[i].num);
l=strlen(s[i].name);
fprintf(fp,"%d ",l);
fputs(s[i].name,fp);
fprintf(fp," %c ",s[i].sex);//注意输出格式
fprintf(fp,"%.2lf %.2lf %.2lf %.2lf %.2lf\n",s[i].score[0],s[i].score[1],s[i].score[2],s[i].avg,s[i].sum);
}
fclose(fp);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
struct stu
{
int num,l;
char name[21],sex;
double score[3];
double avg,sum;
};
int main()
{
FILE *fp;
int n,i,l;
struct stu s;
if((fp=fopen("g:\\student.txt","r"))==NULL)
{
printf("can't open file!\n");
exit(1);
}
while(fscanf(fp,"%d%d ",&s.num,&s.l)!=-1)
{
fgets(s.name,s.l+1,fp);//这里注意读取名字的时候要加上'\0'的长度,即+1
fscanf(fp," %c ",&s.sex);
fscanf(fp,"%lf%lf%lf%lf%lf",&s.score[0],&s.score[1],&s.score[2],&s.avg,&s.sum);
printf("%d ",s.num);
for(i=0; s.name[i]!='\0'; i++)
putchar(s.name[i]);
printf(" %c %.2lf %.2lf %.2lf %.2lf %.2lf\n",s.sex,s.score[0],s.score[1],s.score[2],s.avg,s.sum);
}
fclose(fp);
return 0;
}