1.1文件类型
按存储格式 分为:文本文件、二进制文件
概念上讲,文本文件的数据都是以单个字符的形式进行存放,每个字节存储的是一个字符的ASCII码值,把一批彼此相关的数据以字符的形式存放在一起构成的文件就是文本文件(也叫ASCII码文件)。
二进制文件中的数据是按其在内存中的存储样式原样输出到二进制文件中进行存储的,也就是说,数据原本在内存中会死什么样子,在二进制文件中就还是什么样子。
例如,整数12345,在文本文件中存放时,数字“1”、“2”、“3”、“4”、“5”都是以字符的形式各占一个字节,每个字节中存放的是这些字符的ASCII值,所以要占用5个字节的存储空间;在二进制文件中存放时,因为是整型数据,所以系统分配两个字节的存储空间,也就是说,整数12345在二进制文件中占用两个字节。存放形式如下图
主要区别:
(1)由于存储数据的格式不同,所以在进行读写操作时,文本文件是以字节为单位进行写入或读出;而二进制文件则以变量、结构体等数据块为单位进行读写。
(2)一般来说,文本文件用于存储文字信息,一般由可显示字符构成,如说明性的文档、c语言的源程序文件等都是文本文件;二进制文件用于存储非文本数据,如考试成绩或图像、声音等信息。
1.2 文件指针
C语言中,所有对文件的操作都通过文件指针来完成
变量的指针窒息那个该变量的存储空间;文件的指针 指向描述有关这个文件的相关信息的一个文件信息结构体,该结构体定义在stdio.h头文件中。先声明后使用。
语法格式:
FILE *文件指针名; //功能是声明一个文件指针
1.3 文件缓冲区
文件存储在外存储器上, 外存的数据读写速度相对较慢,所以在对文件进行读写操作时,系统会在内存中为文件的输入或输出开辟缓冲区。
对文件进行输出时,系统首先把输出的数据填入为该文件开辟的缓冲区内,每当缓冲区被填满时,就把缓冲区中的内容一次性地输出到对应的文件中。 当从某个文件输入数据时,首先将从输入文件中输入一批数据放入到该文件的内容缓冲区中,输入语句将从该缓冲区中一次读取数据;当该缓冲区的数据被读完时,将再从输入文件中输入一批数据放入缓冲区
2.文件打开、关闭
对文件读写之前,必须先打开文件;对文件的读写结束之后,应关闭文件.
2.1 fopen()函数
FILE *fp;
fp = fopen("文件名","打开方式");
功能:以某种制定的打开方式打开一个制定的文件,并是文件指针fp指向该文件,文件成功打开之后,对文件的操作就可以直接通过文件指针fp了。文件打开成功,fopen()函数返回一个指向FILE类型的指针值(非0值);指定文件不能打开,返回一个空指针值NULL。
FILE *fp;
if((fp = fopen("abc,txt","r+")) == 0){
printf("Can't open this file
");
exit(0);
}
NULL是stdio.h中定义的一个符号常量,代表数值0,表示控制证。因而有时在程序语中也用NULL代替0. if((fp = fopen("abc.txt","r+")) == NULL)
2.2 fclose()函数
fclose(文件指针);
fclose()函数只有一个参数“文件指针”,它必须是由打开文件函数fopen()得到的,并指向一个已经打开的文件。
功能:关闭文件指针所指向的文件。执行fclose()函数时,若文件关闭成功,返回0,否则返回-1。
2.3 feof()函数 文件结束检测
feof(文件指针);
feof()函数用于检测文件是否结束,既适用于二进制文件,也适用于文本文件。文件指针指向一个已经打开并正在操作的文件
功能:测试文件指针fp所指向的文件是否已督导文件尾部。若已督导文件末尾,返回值为1;否则,返回值为0。
说明:在进行读文件操作时,需要检测是否读到文件的结尾处,常用"while(!feof(fp))"循环语句来控制文件中内容的读取。如当前读取的不是文件尾部,则feof(fp)的值为0,取非运算后值为1,那么循环继续执行;若已读到文件结尾,则feof(fp)的值为1,取非运算后值为0,循环结束,即是读文件操作结束。
3.文件的顺序读写
分 顺序读写和随机读写两种方式。顺序读写方式指的是从文件首部开始顺序读写,不允许跳跃;随机读写方式也叫定位读写,是通过定位函数定位到具体的读写位置,在该位置处直接进行读写操作。一般,顺序读写方式是默认的文件读写方式。
文件的顺序读写常用的函数:
字符输入/输出函数:
字符输入/输出函数:fgetc,fputs
字符串输入/输出函数:fgets,fputs
格式化输入/输出函数:fscanf,fprintf
数据块输入/输出函数:fread,fwrite
3.1 文本文件中字符的输入/输出
文本文件中数据的输入/输出,可以以字符为单位,也可以以字符串为单位。
以字符为单位的输入/输出函数:fgetc()、fputc()
3.1.1 fgetc() 文件字符输入函数
格式:
char ch;
ch = fgetc(文件指针);
功能:该函数从文件指针所指定的文件中读取一个字符,并把该字符的ASCII值赋给变量ch。执行该函数时,如果是督导文件末尾,则函数返回文件结束标志EOF。
说明:文件输入是指从一个已经打开的文件中读出数据,并将其保存到内存变量中,这里的“输入”是相对内存变量而言的。
例,从文本文件读取字符并把其输出到屏幕上:
ch = fgetc(fp);
while(ch != EOF){ //相当于 while(ch != 1)
puchar(ch);
ch = fgetc(fp);
}
EOF字符常量是文本文件的结束标志,不是可输出字符,不能在屏幕上显示。该字符常量在stdio.h中定义为-1,因此当从文件中读入的字符值等于-1时,表示读入的已不是正常的字符,而是文本文件结束符。
3.1.2 fputc() 文件字符输出函数
格式:
fputc(字符,文件指针);
第一个参数 字符,可以是一个普通字符常量,也可以是一个字符变量名;第2个参数”文件指针“指向一个已经打开的文件
功能:把”字符“的ASCII值写入文件指针所指向的文件。若写入成功,则返回字符的ASCII;否则返回文本文件结束标志EOF。
说明:文件输出是指将内存变量中的数据写到文件中,这里的”输出“也是相对内存变量而言的。例:
fputc("a",fp); //把字符"a"的ASCII值写入到fp所指向的文件中
char ch;
fputc(ch,fp); //把变量ch中存放的字符ASCII值写入到fp所指向的文件中
例,利用fgetc()和fputc()建立一个文本文件,并在屏幕上显示文件中的内容
int main(){
FILE *fp1,*fp2;
char c;
if((fp1 = fopen("file1.txt","w")) == 0){
printf("不能打开文件
");
exit(0);
}
printf("输入字符:
");
while((c = getchar()) != '
')
fputc(c,fp1);
fclose(fp1);
if((fp2 = fopen("file1.txt","r")) == 0){
printf("不能打开文件
");
exit(0);
}
printf("输出字符:
");
while((c = fgetc(fp2)) != EOF)
putchar(c);
printf("
");
fclose(fp2);
return 0;
}
3.2 文本文件中字符串的输入/输出
3.2.1 fgets() 字符串输入函数
fgets()函数从文本文件中读取一个字符串,并将其保存到内存变量中。
格式:
fgets(字符串指针,字符个数n,文件指针);
第1个参数“字符串指针”可以是一个字符数组名,也可以是字符指针,用于存放读出的字符串;第2个参数是一个整型数,用来指明读出字符的个数;第3个参数“文件指针”
功能:从文件指针所指向的文本文件中读取n-1个字符,并在结尾处加上" "组成一个字符串,存入“字符串指针”中。若函数调用成功,则返回存放字符串的首地址;若读到文件结尾处或调用失败时,则返回字符常量NULL
满足下列条件之一时,读取过程结束:
(1)已读取了n-1个字符;
(2)当前读取的字符是回车符;
(3)已读取到文件末尾。
3.2.2 fputs() 字符串输出函数
格式:
fputs(字符串,文件指针);
“字符串”可以是一个字符串,也可以是一个字符数组名或指向字符的指针。
功能:将“字符串”写到文件指针所指向的文件中,若写入成功,函数的返回值为0;否则,返回一个非零值。
说明:向文件中写入的字符串中并不包含字符串结束标识符" ".
int main(){
FILE *fp1,*fp2;
char str[10];
if((fp1 = fopen("file2.txt","w")) == 0){
printf("不能创建文件
");
exit(0);
}
printf("输入字符串:
");
gets(str);
while(strlen(str)>0){
fputs(str,fp1);
fputs("
",fp1);
gets(str);
}
fclose(fp1);
if((fp2 = fopen("file2.txt","r")) == 0){
printf("不能打开文件
");
exit(0);
}
printf("输出字符串:
");
while((fgets(str,10,fp2)) != 0)
printf("%s",str);
printf("
");
fclose(fp2);
return 0;
}
//两次enter
3.3 格式化输入/输出
3.3.1 fprintf() 格式化输出函数
与printf()函数相似,只是讲输出的内容存放在一个指定的文件中。
格式:
fprintf(文件指针,格式串,输出项表);
功能:按“格式串”所描述的格式把输出项写入“文件指针”所指向的文件中。成功,返回所写的字节数;否则,返回一个负数。
3.3.1 fscanf() 格式化输出函数
fscanf()与scanf()函数相似,只是输入的数据时来自于文本文件。
一般格式:
fscanf(文件指针,格式串,输入项表);
功能:
从“文件指针”所指向的文本文件中读取数据,按“格式串”所描述的格式输入到指定的内存单元中。
例,用fprintf()函数和fscanf()函数建立文本文件,并读取其中的信息输出到屏幕
int main(){
FILE *fp;
char name1[4][8],name2[4];
int i,score1[4],score2;
if((fp = fopen("file3.txt","w")) == 0){
printf("不能打开文件
");
exit(0);
}
printf("输入数据:姓名 成绩
");
for(i = 1;i < 3;i++){
scanf("%s %d",name1[i],&score1[i]);
fprintf(fp,"%s %d
",name1[i],score1[i]);
}
fclose(fp);
if((fp = fopen("file3.txt","r")) == 0){
printf("不能打开文件
");
exit(0);
}
printf("输出数据:
");
while(!feof(fp)){
fscanf(fp,"%s %d
",name2,&score2);
printf("%s %d
",name2,score2);
}
fclose(fp);
return 0;
}
//输两个学生姓名、成绩
3.4 数据块读写--二进制文件的输入输出
二进制文件,以“二进制数据块”为单位进行数据的读写操作。所谓“二进制数据块”就是指在内存中连续存放的具有若干长度的二进制数据,如整型数据、实型数据或结构体类型数据等,数据块输入/输出函数对于存取结构体类型尤为方便。
3.4.1 fwrite() 数据块输出函数
这里“输出”还是相对于内存变量而言。fwrite()函数是从内存输出数据到指定的二进制文件中
一般格式 :
fwrite(buf,size,count,文件指针);
buf 是输出数据在内存中存放的起始地址,也就是数据块指针;
size 是每个数据块的字节数;
count 用来制定每次写入的数据块的个数;
文件指针是指向一个已经打开文件。
功能:
从以buf为首地址的内存中取出count个数据块(每个数据块为size个字节),写入到“文件指针”指定的文件中。调用成功,该函数返回实际写入的数据块的个数;出错时返回0值。
3.4.2 fread() 数据块输入函数
这里“输入”仍是相对于内存变量而言的。fread()函数是从指定的二进制文件中输出数据到内存单元中
一般格式:
fread(buf,size,count,文件指针);
buf 输入数据在内存中存放的起始地址;
size 是每个数据块的字节数;
count 用来指定每次输出的数据块的个数。
功能:
在文件指针指定的文件中读取count个数据块(每个数据块为size个字节),存放到buf指定的内存单元地址中去。调用成功,函数返回实际读出的数据块个数;出错或遇到文件末尾返回0值。
例,使用fwrite()和fread()函数对 文件进行写入和读取操作
- 文件的随机读写
给定文件当前读写位置的一种读写文件方式,就是允许对文件进行跳跃式读写操作。
定位文件爱你的额当前读写位置,文件位置指针,就是指当前读或写的数据在文件中的位置,实际使用中,有文件指针充当。进行文件读写操作时,总是从文件位置指针开始读其后的数据,然后位置指针移到尚未读的数据之前;进行写操作时,总是从文件位置指针开始去写,然后移到刚写入的数据之后。
1 ftell() 取文件位置指针的当前值
格式:
ftell(fp);
功能:
返回当前文件位置指针fp相对于文件开头的位移量,单位是字节。调用成功返回文件位置指针当前值,否则返回值为-1。
说明:适用于二进制文件和文本文件。
2 fseek 移动文件位置指针
用来一定文件位置指针到指定的位置上,然后从该位置进行读或写操作,从而实现对文件的随机读写功能。
格式:
fseek(fp,offset,from);
其中offset是文件位置指针的位移量,是一个long型的数据,ANSI C标准规定在数字的末尾加一个字母L来表示是Long型。若位移量为正值,表示位置指针的移动是朝着文件尾的方向(从前向后);若位移量为负值,表示位置指针的移动是朝着文件头的方向(从后向前). from是起始点,用以指定位移量是以哪个位置为基准的。
功能:
将文件位置指针从from表示的位置移动offset个字节。若函数调用成功,返回值为0,否则返回非0值。
代表起始点的符号常量和数字及其含义,在fseek函数中使用时两者等价:
3 rewind()函数 置文件位置指针于文件开头
格式:
rewind(fp);
功能:
将文件位置指针移到文件开始位置。该函数只是起到移动文件位置指针的作用,并不带回返回值。
5.文件操作
例,建立两个文本文件f1.txt和f2.txt,从键盘输入字符写入到这两个文本文件中,然后对f1.txt和f2.txt中的字符排序,并合并到一个文件f3.txt中。
void main(){
FILE *fp;
char ch[200],c;
int i = 0,j,n;
if((fp = fopen("f1.txt","w+")) == NULL){
printf("
不能打开文件f1
");
exit(0);
}
printf("写入数据到f1.txt:
");
while((c = getchar()) != '
')
fputc(c,fp);
rewind(fp);
while((c = fgetc(fp)) != EOF)
ch[i++] = c;
fclose(fp);
if((fp = fopen("f2.txt","w+")) == NULL){
printf("
不能打开文件f2
");
exit(0);
}
printf("写入数据到f2.txt:
");
while((c = getchar()) != '
')
fputc(c,fp);
rewind(fp);
while((c = fgetc(fp)) != EOF)
ch[i++] = c;
fclose(fp);
n = i;
for(i = 1;i < n;i++)
for(j = 0;j < n - i;j++)
if(ch[j] > ch[j + 1]){
c = ch[j];
ch[j] = ch[j + 1];
ch[j + 1] = c;
}
if((fp = fopen("f3.txt","w+")) == NULL){
printf("
不能打开文件f3
");
exit(0);
}
for(i = 0;i < n;i++)
fputc(ch[i],fp);
printf("排序并输出:
");
rewind(fp);
while((c = fgetc(fp)) != EOF)
putchar(c);
printf("
");
fclose(fp);
}