一、什么是文件 二、文件的打开和关闭 三、文件的顺序读写 四、文件的随机读写 五、文本文件和二进制文件 六、文件读取结束的判定 七、文件缓冲区一、什么是文件
在程序设计中,我们一般谈的文件有两种:程序文件、数据文件
1.程序文件包括源程序文件(后缀为.c), 目标文件(windows环境后缀为.obj), 可执行程序(windows环境后缀为.exe)
2.数据文件文件的内容不一定是程序,而是程序运行时读写的数据
比如程序运行需要从中读取数据的文件,或者输出内容的文件。
3.文件名
一个文件要有一个唯一的文件标识,以便用户识别和引用。
文件名包含3部分:文件路径 + 文件名 + 文件后缀
例如: c : codetest.txt
缓冲文件系统中,关键的概念是“文件类型指针”,简称“ 文件指针 ”。
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。
这些信息是保存在一个结构体变量中的。该结构体类型是有系统声明的,取名 FILE . 例如, VS2013 编译环境提供的 stdio.h 头文件中有以下的文件类型申明:
struct _iobuf
{
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
不同的
C
编译器的
FILE
类型包含的内容不完全相同,但是大同小异。
每当打开一个文件的时候,系统会根据文件的情况自动创建一个
FILE
结构的变量,并填充其中的信息,
使用者不必关心细节。
一般都是通过一个
FILE
的指针来维护这个
FILE
结构的变量,这样使用起来更加方便。
下面我们可以创建一个
FILE*
的指针变量
:
FILE*pf//文件指针变量pf 是一个指向 FILE类型数据的指针变量,我们可以通过文件指针变量找到与它关联的文件
2.文件在读写之前应该先打开文件,在使用结束之后应该关闭文件
//打开文件 FILE* fopen(const char* filename, const char* mode); //关闭文件 int fclose(FILE* stream)
fopen函数中mode为操作指令字符串,以下就是mode的字符串指令
实例代码:
int main()
{
//打开文件
FILE* pf = fopen("test.bit", "w");
if (pf == NULL)
{
perror(fopen);
return 1;
}
//读文件
.......
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
三、文件的顺序读写
下面来用代码介绍上述函数的功能:
1.fputc--字符输出函数int fputc( int c, FILE *stream );----- c指的是字符
//通过指令"w",将字符一个个运输到文件"test.bit"中
int main()
{
//打开文件
FILE* pf = fopen("test.bit", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
char ch = 'A';
for (ch = 'A';ch <= 'Z'; ch++)
{
fputc(ch, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
2.fgetc--文本行输入函数
int fgetc( FILE *stream ); -----如果fgetc函数读取错误或读到最后一个字符后,将会返回EOF(文件结束标志)
//通过指令"r",将文件"test.bit"中的字符一个个读取到程序中
int main()
{
//打开文件
FILE* pf = fopen("test.bit", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
int ch = 0;
while ((ch = fgetc(pf)) != EOF)// 注意:int,非char,要求处理EOF
{
printf("%c ", ch);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
3.fputs--文本行输出函数
int fputs( const char *string, FILE *stream );
//通过指令"w",将字符串一行一行运输到文件"test.bit"中
int main()
{
//打开文件
FILE* pf = fopen("test.bit", "w");//使用"w"指令,之前文件中存在的内容会被销毁
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件 -- 一行一行的写
fputs("hello worldn", pf);
fputs("Windy Hilln", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
4.fgets---文本行输入函数
char *fgets( char *string, int n, FILE *stream );-----n指读取字符的个数 如果fgets函数读取错误或读到最后一个字符后,将会返回NULL
//通过指令"r",将文件"test.bit"中的字符串一个字符一个字符的读取到程序中
int main()
{
char arr[255] = "abcdefg";
//打开文件
FILE* pf = fopen("test.bit", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
while (fgets(arr, 255, pf) != NULL)
{
printf("%s", arr);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
5.fprintf--格式化输出函数
int fprintf( FILE *stream, const char *format [, argument ]...);
//fprintf函数可以写入任何类型数据从程序到文件中,例如结构体变量
struct S
{
char name[20];
int age;
double d;
};
int main()
{
struct S pep = { "张三",29,89.9 };
//打开文件
FILE* pf = fopen("test.bit", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
fprintf(pf, "%s %d %lf", pep.name, pep.age, pep.d);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
6.fscanf--格式化输入函数
int fscanf( FILE *stream, const char *format [, argument ]... );
//fscanf函数可以从文件中读取任何类型数据到程序中,例如结构体变量
struct S
{
char name[20];
int age;
double d;
};
int main()
{
struct S s = { 0 };
//打开文件
FILE* pf = fopen("test.bit", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
fscanf(pf, "%s%d%lf", s.name, &s.age, &s.d);
printf("%s %d %lfn", s.name, s.age, s.d);
fprintf(stdout, "%s %d %lfn", s.name, s.age, s.d);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
7.spritnf--- 将格式化数据 转换成 字符串数据
sscanf--- 将字符串数据 转换成 格式化数据int sprintf( char *buffer, const char *format [, argument] ... );
int sscanf( const char *buffer, const char *format [, argument ] ... );
struct S
{
char name[20];
int age;
double d;
};
int main()
{
char buf[256] = "xxxxxxx";
struct S s = { "元歌",19,14.4 };
struct S tum = { 0 };
sprintf(buf, "%s %d %.2lf", s.name, s.age, s.d);
printf("%sn", buf);//字符串
//从buf字符串中提取结构体数据
sscanf(buf, "%s%d%lf",tum.name,&(tum.age),&(tum.d));
printf("%s %d %.2lf", tum.name, tum.age, tum.d);//格式化的形式
return 0;
}
8.fread---二进制输入
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );
//通过指令"wb",将任何类型的数据以二进制的方式写入"test.bit"文件中
struct S
{
char name[20];
int age;
double d;
};
int main()
{
struct S s = { "元歌",19,14.4 };
//打开文件
FILE* pf = fopen("test.bit", "wb"); //"wb+"为了读和写,新建一个新的二进制文件
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
//二进制的方式写文件
fwrite(&s, sizeof(s), 1, pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
9.fwrite--二进制输出
size_t fwrite( const void *buffer, size_t size, size_t count, FILE *stream );
//通过指令"rb",将文件"test.bit"中的数据以二进制的方式读取到程序中
struct S
{
char name[20];
int age;
double d;
};
int main()
{
struct S s = { 0 };
//打开文件
FILE* pf = fopen("test.bit", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
//二进制的方式读
fread(&s, sizeof(s), 1, pf);
printf("%s %d %.2lfn", s.name, s.age, s.d);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}



