C文件的有关基础知识
什么是文件
程序文件、数据文件。操作系统把各种设备都统一作为文件来处理。通常将输入输出形象地称为流,即数据流。一个输入输出流就是一个字符流或字节(内容为二进制数据)流。
文件名
文件标识包括3部分:文件路径,文件名主干,文件后缀。
文件的分类
数据文件可分为ASCII文件和二进制文件。字符一律以ASCII形式存储,数值型数据既可以用ASCII形式存储,也可以用二进制形式存储。
用ASCII码形式输出时字节与字符一一对应,一个字节代表一个字符。
文件缓冲区
ANSI C标准采用”缓冲文件系统”处理数据文件,指系统自动地在内存区为程序中每一个正在使用的文件开辟一个文件缓冲区。
文件类型指针
文件类型指针简称文件指针。每个被使用的文件都在内存中开辟一个相应的文件信息区,用来存放文件的有关信息,这些信息保存在一个结构体变量中,取名为FILE,在stdio.h文件中声明。
一般不定义FILE类型的变量命名,也就是不通过变量的名字来引用这些变量,而是设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。如下:1
FILE *fp;
通过文件指针变量能够找到与它关联的文件。
打开与关闭文件
用fopen函数打开数据文件
fopen函数的调用方式为:fopen(文件名,使用文件方式)。1
2FILE *fp;
fp = fopen("a1", "r");
使用文件方式还包括:只读(r), 只写(w), 等等。常用以下方法打开一个文件:1
2
3
4if((fp == fopen("file1", "r")) == NULL){
printf("cannot open this file\n");
exit(0);
}
用fclose函数关闭数据文件
关闭文件用fclose函数,fclose函数调用的一般形式为:fclose(文件指针)。1
fclose(fp);
该函数也带回一个值,当成功地执行了关闭操作,则返回值为0,否则返回EOF(-1)。
顺序读写数据文件
向文件读写字符
- 函数名:fgetc,调用方式:fgetc(fp),功能:从fp指向的文件读入一个字符,返回值:读成功,带回所读的字符,失败则返回文件结束标志EOF(即-1)。
- 函数名:fputc,调用方式:fputc(ch,fp),功能:把字符ch写到文件指针变量fp所指向的文件中,返回值:输出成功,返回值就是输出的字符,失败则返回EOF。
举例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
int main(){
FILE *in, *out;
char ch, infile[10], outfile[10];
printf("输入读入文件的名字:");
scanf("%s", infile);
printf("输入输出文件的名字:");
scanf("%s", outfile);
if((in=fopen(infile,"r"))==NULL){
printf("无法打开文件\n");
exit(0);
}
if((out=fopen(outfile,"w"))==NULL){
printf("无法打开文件\n");
exit(0);
}
ch = fgetc(in);
while(!feof(in)){ //如果未达到输入文件的结束标志
fputc(ch,out); //将ch写到输出文件
putchar(ch); //将ch显示到屏幕上
ch = fgetc(in); //再从输入文件读入一个字符,赋给变量ch
}
putchar(10);
fclose(in);
fclose(out);
return 0;
}
向文件读写字符串
- 函数名:fgets,调用形式:fgets(str,n,fp),功能:从fp指向的文件读入一个长度为n-1的字符串(最后会加上一个’\0’结束符),存放到字符数组str中,返回值:读成功,返回地址str,失败则返回NULL。
函数原型:1
char* fgets(char* str, int n, FILE* fp);
- 函数名:fputs,调用形式:fputs(str,fp),功能:把str所指向的字符串写到文件指针变量fp所指向的文件中,返回值:输出成功,返回0,否则返回非0值。
函数原型:1
int fputs(char *str, FILE *fp);
举例:从键盘读入若干个字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件中保存。
具体分为以下步骤:
- 从键盘中读入n个字符串,存放在一个二维字符数组中,每个以为数组存放一个字符串;
- 对字符数组中的n个字符串按字母顺序排序,排好序的字符串仍存放在字符数组中;
- 将字符数组中的字符串顺序输出。
1 |
|
用格式化的方式读写文本文件
对文件进行格式化输入输出要用fprintf函数和fscanf函数,从函数名可以看到,它们只是在printf和scanf的前面加了一个f。它们的作用与printf和scanf函数相仿,都是格式化读写函数。不同点是,fprintf和fscanf函数的读写对象不是终端,而是文件。
一般调用方式为:
fprintf(文件指针,格式字符串,输出表列);
fscanf(文件指针,格式字符串,输入表列);
例如:1
2fprintf(fp, "%d,%6.2f", i, f);
fscanf(fp, "%d,%f", &i, &f);
在内存与磁盘频繁交换数据的情况下,最好不用fprintf和fscanf函数,而用下面介绍的fread和fwrite函数进行二进制的读写。
用二进制方法向文件读写一组数据
一般调用形式为:
fread(buffer, size, count, fp):
buffer是一个地址,对fread来说,它是用来存放从文件读入的数据的存储区的地址;对fwrite来说,是把此地址开始的存储区中的数据向文件输出。
size:要读写的字节数
count:要读写多少个数据项(每个数据项长度为size)
fp: FILE类型指针。
例如: fread(f, 4, 10, fp)表示f是一个float型数组名(代表数组首元素地址),该函数从fp所指向的文件读入10个4个字节的数据,存储到数组f中。
随机读写数据文件
文件位置标记及其定位
为了对读写进行控制,系统为每个文件设置了一个文件读写位置标记(简称文件位置标记或文件标记),用来指示“接下来要读写的下一个字符的位置。
一般情况下,在对字符文件进行顺序读写时,文件位置标记指向文件开头,这时如果对文件进行读操作,就读1个字符,然后文件位置标记向后移一个位置。
我们可以根据读写的需要,人为地移动文件位置标记的位置,这时便是随机读写。
文件位置标记的定位
可以强制使文件位置标记指向人们指定的对象。可以用以下函数实现:
- 用rewind函数使文件标记位置指向文件开头,无返回值,同时feof函数的值会恢复为0: rewind(fp);
- 用fseek函数改变文件位置标记,调用形式为:fseek(文件类型指针,位移量,起始点) 其中,起始点用0,1,或2代替,0表示文件开始位置,1表示当前位置,2表示文件末尾位置。“位移量”指以起始点为基点,向前移动的字节数,位移量应是long型数据(在数字的末尾加一个字母L,就表示是long型)。
- ftell函数可测定文件位置标记的当前位置,即用于得到文件位置指针当前位置相对于文件首的偏移字节数。
举例:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
struct Student_type{
char name[10];
int num;
int age;
char addr[15];
}stud[10];
int main(){
int i;
FILE *fp;
if((fp=fopen("stu.dat","rb"))==NULL){
printf("cannot open file\n");
exit(0);
}
for(i=0; i<10; i+=2){
fseek(fp,i*sizeof(struct Student_type),0); //移动文件位置标记
fread(&stud[i],sizeof(struct Student_type),1,fp); //读一个数据块到结构体变量
printf("%-10s %4d %4d %-15s\n", stud[i].name, stud[i].num, stud[i].age, stud[i].addr);
}
}
文件读写的出错检测
ferror函数
在调用各种输入输出函数时如果出现错误,除了函数返回值有所反映外,还可以用ferror函数检查。其一般调用形式为ferror(fp)。如果ferror返回值为0,表示未出错。
chearerr函数
作用是使文件出错标记和文件结束标记置为0。假设在盗用一个输入输出函数时出现错误,ferror函数值为一个非零值,应该立即调用clearerr(fp),使ferror(fp)的值变为0,以便再进行下一次的检测。