目录
1. 前言
1.1文件
文件根据功能可以划分为两种:
1.程序文件
如源程序⽂件(后缀为.c),⽬标⽂件(windows环境后缀为.obj),可执⾏程序(windows
2.数据文件
程序读写时的数据。
根据数据的组织形式,数据⽂件被分为:
2.1.⽂本⽂件
在外存上以ASCII码的形式存储,需要在存储前转换,以ASCII字符的形式存储的⽂件。
2.2.⼆进制⽂件
数据在内存中以⼆进制的形式存储,不加转换的输出到外存的⽂件
本篇我们将讨论如何处理数据文件。
1.2 文件指针
文件指针指向文件信息区,而文件信息区中储存中文件相关的信息。通过⽂件指针变量我们能够间接找到与 它关联的⽂件。
FILE* pf//文件指针变量
2. ⽂件的打开和关闭
//打开⽂件
FILE * fopen ( const char * filename, const char * mode );
//关闭⽂件
int fclose ( FILE * stream );
2.1 文件名注意事项
1.文件地址中的的"/"应该改为"\"或者"//"。
2.文件应该放在与源文件同一目录下("test.txt"),否则需要写明具体文件地址,像这样("D:\\code\\c_biggner\\2024.3.23\\2024.3.23\\test.txt")
2.2 打开模式
打开模式 功能 若文件不存在
"r"(只读) | 读取:打开要执行输入操作的文件。文件必须存在。 | 报错 |
"w"(只写) | 写:为输出操作创建一个空文件。如果已经存在同名的文件,则将丢弃其内容,并将该文件视为一个新的空文件。 | 创建新文件 |
"a"(追加) | 附加:在文件的末尾打开文件以进行输出。输出操作总是在文件的末尾写入数据,并展开它。忽略重新定位操作(fseek、设置、倒带)。如果该文件不存在,则会创建该文件. | 创建新文件 |
"r+"(读写) | 读取/更新:为了读和写,打开一个文件。该文件必须存在。 | 报错 |
"w+"(读写) | 写入/更新:为了读和写,创建一个空文件。如果已经存在同名文件,其内容将被丢弃,并且该文件被视为新的空文件。 | 创建新文件 |
"a+"(读写) | 附加/更新:打开一个文件,在文件的末尾写入数据。 | 创建新文件 |
“rb+”(读写) (无b就不能写) | 为了读和写打开⼀个⼆进制⽂件 | 报错 |
“wb+”(读写) (无b就不能写) | 为了读和写,新建⼀个新的⼆进制⽂件 | 创建新文件 |
“ab+” (读写) (无b就不能写) | 打开⼀个⼆进制⽂件,在⽂件尾进⾏读和写 | 创建新文件 |
示例
#include <stdio.h>
int main ()
{
FILE * pFile;
//打开⽂件
pFile = fopen ("file.txt","w");
//⽂件操作
...
//关闭⽂件
fclose (pFile);
}
return 0;
}
3. ⽂件的顺序读写
3.1fgetc&fputc
函数 | 功能 | 适⽤范围 |
int fgetc ( FILE * stream ); | 字符输⼊函数 | 所有输⼊流 |
int fputc ( int character, FILE * stream ); | 字符输出函数 | 所有输出流 |
3.2 fgets&fputs
函数 | 功能 | 适⽤范围 |
char * fgets ( char * str, int num, FILE * stream ); | ⽂本⾏输⼊函数 | 所有输⼊流 |
int fputc ( int character, FILE * stream ); | ⽂本⾏输出函数 | 所有输出流 |
3.3 fscanf&fprintf
函数 | 功能 | 适⽤范围 |
int fscanf ( FILE * stream, const char * format, ... ); | 格式化输⼊函数 | 所有输⼊流 |
int fprintf ( FILE * stream, const char * format, ... ); | 格式化输出函数 | 所有输出流 |
//写文件
printf(pf, "%s %d %f", s.name, s.age, s.score);
//读文件
fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
3.4有关“流”?“所有输入/出流”?
看到这里,你或许会产生疑惑:什么是流?
3.4.1流
3.4.3所有输入输出流的体现
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main() {
int a;
fscanf(stdin, "%d",&a);
fprintf(stdout, "%d", a);
return 0;
}
像这样,可以将代码直接从键盘中输入,输出在屏幕上。(等同于scanf,printf了)
3.5 fread&fwrite
函数 | 功能 | 适⽤范围 |
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream ); | ⼆进制输⼊ | ⽂件 |
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream ); | ⼆进制输出 | ⽂件 |
/* fwrite example : write buffer */
#include <stdio.h>
int main ()
{
FILE * pFile;
char buffer[] = { 'x' , 'y' , 'z' };
pFile = fopen ("myfile.bin", "wb");
fwrite (buffer , sizeof(char), sizeof(buffer), pFile);
fclose (pFile);
return 0;
}
int main()
{
int arr[5] = {0};
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1; }
//读数据
fread(arr, sizeof(arr[0]), 5, pf);//以二进制的形式写进去的
fclose(pf);
pf = NULL;
return 0;
}
4. ⽂件的随机读写
4.1 fseek
int fseek ( FILE * stream, long int offset, int origin );
根据⽂件指针的位置和偏移量来定位⽂件指针。
参数一:流(文件指针)
参数二:偏移量
参数三:用作偏移量参考的位置
Origin | 参考位置 |
SEEK_SET | 文件的开始 |
SEEK_CUR | 文件指针的当前位置 |
SEEK_END | 文件结束 |
4.2 ftell
long int ftell ( FILE * stream );
4.3 rewind
void rewind ( FILE * stream );
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读文件
int ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, 0, SEEK_END);//把指针放到距文件末尾偏移量为0的位置(即文件末尾)
printf("%d\n", ftell(pf));//打印指针距离文件起始位置的偏移量,(size)
rewind(pf);//将指针重新设置回文件起始位置
printf("%d\n",ftell(pf);//打印指针距离文件起始位置的偏移量,(0)
fclose(pf);
pf = NULL;
return 0;
}
5. ⽂件读取结束的判定
5.1 文本文件
fgetc()用返回值是否等于EOF来判断文件读取是否结束
fgets()用返回值是否等于NULL来判断文件读取是否结束
5.2 二进制文件
5.3 feof()函数
5.4 ferror()函数
这个函数与feof()函数是相反的,用来判断文件读取结束是否是异常情况。
返回值:文件读取正常,遇到文件末尾结束,就返回0,异常就返回非0值。
6. ⽂件缓冲区
文件并不是直接输入输出的。它们通常会先汇集到文件缓冲区,当缓冲区被充满,再从文件缓冲区输入输出到目的地。
如果喜欢文章,不要忘了三连支持一下博主嗷~