1. 什么是文件
文件分为两种, 程序文件 和 数据文件
- 程序文件。包括源文件(后缀为.c)、目标文件(后缀为.obj)、可执行文件(后缀为.exe)等。这种文件的内容是可执行代码。
- 数据文件。如一批学生的成绩数据等。
2. 打开与关闭文件
fopen函数打开数据文件,fclose函数关闭数据文件。
-
通常将
fopen
函数的返回值赋给一个指向文件的指针变量FILE *fp ; // 定义一个指向文件的指针变量
fp = fopen("a1", "r");
-
用
fclose
函数关闭数据文件fclose(fp);
3. 顺序读写数据文件
怎样向文件读写字符
栗1:
从键盘输入一些字符,逐个把它们送到磁盘上去,直到用户输入一个"#"为止
#include <stdlib.h>
#include <stdio.h>
int main()
{FILE *fp;
char ch,filename[10];
printf("请输入所用的文件名:");
scanf("%s",filename);
if((fp=fopen(filename,"w"))==NULL) // 打开输出文件并使fp指向此文件
{
printf("无法打开此文件\n"); // 如果打开时出错,就输出"打不开"的信息
exit(0); // 终止程序
}
ch=getchar( ); // 此语句用来接收在执行scanf语句时最后输入的回车符
printf("请输入一个准备存储到磁盘的字符串(以#结束):");
ch=getchar( ); // 接收从键盘输入的第一个字符
while(ch!='#') // 当输入'#'时结束循环
{
fputc(ch,fp); // 向磁盘文件输出一个字符
putchar(ch); // 将输出的字符显示在屏幕上
ch=getchar(); // 再接收从键盘输入的一个字符
}
fclose(fp); // 关闭文件
putchar(10); // 向屏幕输出一个换行符,换行符的ASCII代码为10
return 0;
}
栗2:
将一个磁盘文件中的信息复制到另一个磁盘文件中。 今要求将上例建立的file1.dat文件中的内容复制到另一个磁盘文件file2.dat中。
#include <stdio.h>
#include <stdlib.h>
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);
}
while(!feof(in)) // 如果未遇到输入文件的结束标志
{ch=fgetc(in); // 从输入文件读入一个字符,暂放在变量ch中
fputc(ch,out); // 将ch写到输出文件中
putchar(ch); // 将ch显示在屏幕上
}
putchar(10); // 显示完全部字符后换行
fclose(in); // 关闭输入文件
fclose(out); // 关闭输出文件
return 0;
}
4. 向文件中读写一个字符串
函数名 | 调用形式 | 功能 | 返回值 |
---|---|---|---|
fgets | fgets(str,n,fp) | 从fp指向的文件读入一个长度为 (n-1) 的字符串,并在最后加一个‘\0’字符, 然后把这 n 个字符存放到字符数组 str中 | 读成功,返回地址str,失败则返回NULL |
fputs | fputs(str,fp) | 把str所指向的字符串写到文件指针变量 fp 所指向的文件中 | 输出成功,返回0;否则返回非0值 |
栗3:
从键盘读入若干字符串,对它们按字母大小的顺序排序,然后把排好序的字符串送到磁盘文件中保存
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE *fp;
char s[3][20],temp[20],filename[20];
int i,j,k,n=3;
for(i=0;i<n;i++){
printf("请输入第%d个字符串: ",i+1);
gets(s[i]);
}
for(i=0;i<n-1;i++){
k = i;
for(j=i+1;j<n;j++)
if(strcmp(s[k],s[j])<0) k = j;
if(k!=i){
strcpy(temp,s[i]);
strcpy(s[i],s[k]);
strcpy(s[k],temp);
}
}
printf("请输入磁盘文件名:");
scanf("%s",filename);
// if((fp=fopen("D:\\CC\\string.bat","w"))==NULL)指定其他磁盘文件注意路径格式
if((fp=fopen(filename,"w"))==NULL){
printf("打开文件失败!");
exit(0);
}
printf("\n结果为:\n");
for(i=0;i<n;i++){
fputs(s[i],fp);
fputs("\n",fp);
printf("%s\n",s[i]);
}
return 0;
}
5. 用格式化的方式读写文件
与printf
和 scanf
明显的不同是 fprintf
和 fscanf
函数的读写对象不是终端而是文件,它们一般的调用方式为:
fprintf(文件指针,格式字符串,输出表列);
fscanf(文件指针,格式字符串,输入表列);
例如:
1. fprintf(fp,"%d, %6.2f", i, f);
它的作用是将int
型变量i
和 float
型变量 f
的值按 %d
和 %6.2f
的格式输出到fp
指向的文件中。
2. fscanf(fp,"%d, %f", &i, &f);
磁盘文件上如果有 "3, 4.5"
,则从磁盘文件中读取整数3
送给整型变量i
,读取实数4.5
送给float
型变量f
。
6. 用二进制方式向文件读写一组数据
它们一般的调用方式为:
fread(buffer,size,count, fp);
fwrite(buffer,size,count, fp);
其中,
buffer:
是一个地址。对fread
来说,它是用来存放从数据文件存储区的地址。对fwrite
来说,把此地址开始的存储区的数据向文件输出。
size:
要读写的字节数。
count:
要读写多少个数据项(每个数据项的长度为size)。
fp:
FILE
类型的指针。
栗4:
从键盘输入10个学生的有关数据,然后把它们转存到磁盘文件上去。
#include<stdio.h>
#define N 3
struct student
{
char name[10];
int num;
int age;
}stud[N]; //定义全局结构体数组stud,包含3个学生数据
//对所要调用的函数进行声明
void input();
void save();
void readFile();
int main()
{
printf("please input student's message:\n");
input();
save();
readFile();
return 0;
}
/*
*函数名称:input()
*函数功能:给stud数组中的数据赋值
*返回值:void
*/
void input()
{
for(int i=0;i<N;i++)
{
scanf("%s %d %d",&stud[i].name,&stud[i].num,&stud[i].age);
}
printf("\n");
}
/*
*函数名称:readFile()
*函数功能:从键盘上读取输入的学生数据
*返回值:void
*/
void readFile()
{
FILE *p;
int i;
if((p=fopen("stu_dat","rb"))==NULL)
{
printf("cannot open the file\n");
return;
}
for(i=0; i<N; i++)
{
fread(&stud[i],sizeof(struct student),1,p);
printf("%-10s %4d %4d\n",stud[i].name,stud[i].age,stud[i].num);
}
fclose(p);
return;
}
/*
*函数名称:save()
*函数功能:向文件输出学生的数据
*返回值:void
*/
void save()
{
int i;
FILE *p;
if((p=fopen("stu_dat","wb"))==NULL)//打开输出文件
{
printf("cannot open file\n");
return;
}
for(i=0;i<N;i++)
{
if(fwrite(&stud[i],sizeof(struct student),1,p)!=1)
{
printf("file write error\n");
}
}
fclose(p);
}
7. 随机读写数据文件
例如文件中有1000个数据,若只查第1000个数据,必须先逐个读入前面999个数据,才能读入第1000个数据。
1). 文件位置标记及其定位
2). 文件位置标记的定位
1. rewind 函数使文件位置标记重新返回文件的开头,此函数没有返回值
有一个磁盘文件,内有一些信息。要求第1次将它的内容显示在屏幕上,第2次把它复制到另一份文件上。
#include<stdio.h>
int main()
{
FILE *fp1,*fp2;
fp1=fopen("file1.dat","r"); // 打开输入文件
fp2=fopen("file2.dat","w"); // 打开输出文件
while(!feof(fp1)) putchar(getc(fp1)); // 逐个读入字符并输出到屏幕,feof函数是判断文件位置标记是否到文件末尾
putchar(10); // 输出一个换行
rewind(fp1); // 使文件位置指示器返回文件头
while(!feof(fp1)) putc(getc(fp1),fp2); // 从文件头重新逐个读字符,输出到file2文件
fclose(fp1);fclose(fp2);
return 0;
}
2. fseek 函数改变文件位置标记
fseek
函数的调用方式为:
fseek(文件类型指针,位移量,起始点)
"位移量"以"起始点"为基点,向前移动的字节数。位移量应是long
型数据 (在数字的末尾加上一个字母L
,就表示是long
型)。
fseek 函数一般用于二进制文件。下面是 fseek 函数调用的几个例子:
fseek(fp, 100L, 0); // 将文件位置标记向前移动离文件开头100个字节处
fseek(fp, 50L, 1); // 将文件位置标记向前移动离当前位置 50个字节处
fseek(fp, -10L, 2); // 将文件位置标记从文件末尾处向后退 10 个字节
3. ftell 函数的作用是得到文件位置标记的当前位置
i = ftell(fp); // 变量 i 存放文件当前位置
if (i == -1L) printf("error\n"); // 如果调用函数时出错,输出"error"
8. 随机读写
有了 rewind 和 fseek 函数,就可以实现随机读写了。
在磁盘文件上存入10个学生的数据。要求将1,3,5,7,9个学生数据输入计算机,并在屏幕上显示出来
#include<stdio.h>
#include <stdlib.h>
struct Student_type //学生数据类型
{
char name[10];
int num;
int age;
char addr[15];
}stud[10];
int main()
{
int i;
FILE *fp;
if((fp=fopen("file1.dat","rb"))==NULL) //以只读方式打开二进制文件
{
printf("can not 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);
//在屏幕输出
}
fclose(fp);
return 0;
}
9. 文件读写的出错检测
C提供一些函数用来检查输入输出函数调用时可能出现的错误。
1). ferror函数
它的一般调用形式为: ferror(fp);
说明:
在调用各种输入输出函数(如putc,getc,fread,fwrite等)时,如果出现错误,除了函数返回值有所反映外,还可以用ferror函数检查。
如果ferror返回值为0(假),表示未出错;如果返回一个非零值,表示出错。
2). clearerr函数
说明:
clearerr
的作用是使文件出错标志和文件结束标志置为0。
假设在调用一个输入输出函数时出现错误,ferror
函数值为一个非零值。应该立即调用clearerr(fp)
,使ferror(fp)
的值变成0,以便再进行下一次的检测。
只要出现文件读写出错标志,它就一直保留,直到对同一文件调用 clearerr
函数或 rewind
函数,或任何其他一个输入输出函数。
注:对同一个文件每一次调用输入输出函数,都会产生一个新的ferror函数值,因此,应当在调用一个输入输出函数后立即检查ferror
函数的值,否则信息会丢失。在执行fopen
函数时,ferror
函数的初始值自动置为0。
https://blog.csdn.net/weixin_30883777/article/details/96493618
来源:CSDN
作者:北木.
链接:https://blog.csdn.net/weixin_43283397/article/details/104059483