每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字、状态、位置等)。这些信息是保存在一个结构体变量中。该结构体类型是有系统声明的,取名FILE.
2、打开文件fopen和关闭文件fcloseFILE * fopen ( const char * filename, const char * mode );
filename为文件命,如果打开的文件在工程目录下需要表明文件的绝对位置,mode为文件的方式。
| 文件使用方式 | 含义 | 如果指定文件不存在 |
| "r"(只读) | 为了输入数据,打开一个已经存在的文文件 | 出错 |
| "w"(只写) | 为了输出数据,打开一个文本文件,如果文件存在,会将原文件的内容销毁 | 建立一个新的文件 |
| "a"(追加) | 向文本文件尾添加数据 | 建立一个新的文件 |
| "rb"(只读) | 为了输入数据,打开一个二进制文件 | 出错 |
| "wb"(只写) | 为了输出数据,打开一个二进制文件 | 建立一个新的文件 |
| "ab"(追加) | 向一个二进制文尾添加数据 | 出错 |
| "r+"(读写) | 为了读和写,打开一个文本文件 | 出错 |
| "w+"(读写) | 为了读和写,建立一个新的文件 | 新建一个新的文件 |
| "a+"(读写) | 打开一个文件,在文件尾进行读写 | 建立一个新的文件 |
| "rb+"(读写) | 为了读和写打开一个二进制文件 | 出错 |
| "wb+"(读写) | 为了读和写,新建一个新的二进制文件 | 建立一个新的文件 |
| "ab+"(读写) | 打开一个二进制文件,在文件尾进行读和写 | 建立一个新的文件 |
int fclose ( FILE * stream );
fclose:关闭文件的函数
#include3、文件的顺序读写 1、字符输出函数fputc#include #include int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { printf("open file for writing :%s", strerror(errno)); return 0; } //写文件 //关闭 fclose(pf); pf = NULL; return 0; }
int fputc ( int character, FILE * stream );
将一个字符写入到输出流,如果成功,返回写入字符的ASCAII码值,如果失败返回EOF
#include2、字符输入函数fgetc#include #include int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { printf("open file for writing :%s", strerror(errno)); return 0; } //写文件 for (int i = 'a'; i <= 'z'; i++) { fputc(i, pf); } //关闭 fclose(pf); pf = NULL; return 0; }
int fgetc ( FILE * stream );
从流里得到一个字符,成功返回读到的字符,如果文件结果或者读取错误返回EOF
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
printf("open file for writing :%s", strerror(errno));
return 0;
}
int ch = 0;
//读文件
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
//关闭
fclose(pf);
pf = NULL;
return 0;
}
3、文本输出函数fputs
int fputs ( const char * str, FILE * stream );
写入一个字符串,成功返回一个非负值,失败返回EOF
#include4、文本输入函数fgets#include #include int main() { FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { printf("open file for writing :%s", strerror(errno)); return 0; } //写文件 fputs("abcdef", pf); //关闭 fclose(pf); pf = NULL; return 0; }
char * fgets ( char * str, int num, FILE * stream );
从sream中读取字符串到一个字符数组,num为最大的读取数(实际读的个数为num-1个),成功返回这个字符数组,读取失败或者读取结束返回NULL
#include5、格式化输出函数fprintf#include #include int main() { FILE* pf = fopen("test.txt", "r"); if (NULL == pf) { printf("open file for writing :%s", strerror(errno)); return 0; } //读文件 char buf[100] = {0}; fgets(buf, 3, pf); printf("%sn", buf); //关闭 fclose(pf); pf = NULL; return 0; }
int fprintf ( FILE * stream, const char * format, ... );
将格式化的数据写到stream
#include6、格式化输入函数fscanf#include #include typedef struct Stu { char name[5]; int age; char sex[5]; }Stu; int main() { Stu s1 = { "lisi",20,"male" }; FILE* pf = fopen("test.txt", "w"); if (NULL == pf) { printf("open file for writing:%s", strerror(errno)); return 0; } fprintf(pf, "%s %d %s", s1.name,s1.age, s1.sex); //关闭 fclose(pf); pf = NULL; return 0; }
int fscanf ( FILE * stream, const char * format, ... );
将格式化的数据读入stream
#include7、二进制输出fwrite#include #include typedef struct Stu { char name[5]; int age; char sex[5]; }Stu; int main() { Stu s1 = { "lisi",20,"male" }; Stu s2 = { 0 }; FILE* pf = fopen("test.txt", "r"); if (NULL == pf) { printf("open file for reading:%s", strerror(errno)); return 0; } fscanf(pf, "%s %d %s", s2.name, &s2.age, s2.sex); printf("%s %d %s", s2.name, s2.age, s2.sex); //关闭 fclose(pf); pf = NULL; return 0; }
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
从ptr开始,写入count*size大小的数据到stream
#define _CRT_SECURE_NO_WARNINGS #include8、二进制输出fread#include #include typedef struct Stu { char name[10]; int age; char sex[10]; }Stu; int main() { Stu s[2] = { {"lisi",20,"male"},{"zhangsan",18,"female"}}; FILE* pf = fopen("test.txt", "wb"); if (NULL == pf) { printf("open file for writing:%s", strerror(errno)); return 0; } //写文件 fwrite(s, sizeof(Stu), 2, pf); //关闭 fclose(pf); pf = NULL; return 0; }
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
从stream中读取大小为size*count的数据,返回成功读取到的元素个数
#include#include #include typedef struct Stu { char name[10]; int age; char sex[10]; }Stu; int main() { Stu s[2] = {0}; FILE* pf = fopen("test.txt", "rb"); if (NULL == pf) { printf("open file for reading:%s", strerror(errno)); return 0; } //读文件 fread(s, sizeof(Stu), 2, pf); for (int i = 0; i < 2; i++) { printf("%s %d %s n", s[i].name, s[i].age,s[i].sex); } //关闭 fclose(pf); pf = NULL; return 0; }
需要注意fread函数返回的是读取的元素个数,所以当返回值小于count的时候说明数据已经全部读完
4、对比scanf/fscanf/sscanf/printf/fprintf/sprintfscanf从标准输入流(stdin)上进行格式化输入的函数
printf向标准输出流(stdout)上进行格式化的输出函数
fsacnf可以从标准输入流(stdin)或者指定的文件流上读取格式化的数据
fprintf把数据按照格式的方式输出到标准输出流(stdout)或者指定的文件流
sscanf将字符串转化成格式化的数据
int sscanf ( const char * s, const char * format, ...);
sprintf将格式化的数据转化成字符串
int sprintf ( char * str, const char * format, ... );
#include#include #include typedef struct Stu { char name[10]; int age; char sex[10]; }Stu; int main() { Stu s= {"zhangsan",12,"male"}; char buf[100]; sprintf(buf,"%s %d %s", s.name, s.age, s.sex); printf("%s", buf); return 0; }
#define _CRT_SECURE_NO_WARNINGS #include5、文件的随机读写 1、fseek#include #include typedef struct Stu { char name[10]; int age; char sex[10]; }Stu; int main() { Stu s1= {"zhangsan",12,"male"}; Stu s2 = { 0 }; char buf[100]; sprintf(buf,"%s %d %s", s1.name, s1.age, s1.sex); sscanf(buf, "%s %d %s", s2.name, &s2.age, s2.sex); printf("%s %d %s", s2.name,s2.age,s2.sex); return 0; }
int fseek ( FILE * stream, long int offset, int origin );
根据文件指针的位置和偏移量来定位文件指针
offset为偏移量,origin为起始位置
origin有三个状态
1.SEEK_SET 文件的开始位置
2.SEEK_CUR当前文件指针所指的位置
3.SEEK_END文件结束的位置
比如:
#define _CRT_SECURE_NO_WARNINGS #include#include #include int main() { FILE* pw = fopen("test.txt", "w"); if (NULL == pw) { printf("open file for writing: %s", strerror(errno)); return 0; } fputs("abcdef", pw); fflush(pw);//fputs会把数据先写入缓存区,而不是直接进文件,所以需要刷新缓冲区,让文件写入,方便后面的读 FILE* pr = fopen("test.txt", "r"); if (NULL == pr) { printf("open file for reading:%s", strerror(errno)); return 0; } //直接读到f fseek(pr, -1, SEEK_END); int ch = 0; ch = fgetc(pr); printf("%c", ch); fclose(pr); pr = NULL; //将x写到c的位置 fseek(pw, 2, SEEK_SET); fputc('x', pw); fclose(pw); pw = NULL; return 0; }
2、ftell
long int ftell ( FILE * stream );
返回文件指针相对于起始位置的偏移量
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
printf("open file for writing :%s", strerror(errno));
return 0;
}
int ch = 0;
//读文件
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
//进行3次读取后,文件指针与起始位置的偏移量应该为3
printf("%dn", ftell(pf));
//关闭
fclose(pf);
pf = NULL;
return 0;
}
3、rewind
void rewind ( FILE * stream );
让文件指针的位置回到文件的起始位置
int main()
{
FILE* pf = fopen("test.txt", "r");
if (NULL == pf)
{
printf("open file for writing :%s", strerror(errno));
return 0;
}
int ch = 0;
//读文件
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
ch = fgetc(pf);
printf("%cn",ch);
//进行3次读取后,文件指针与起始位置的偏移量应该为3
printf("%dn", ftell(pf));
//将文件指针的位置回到文件的起始位置
rewind(pf);
printf("%dn", ftell(pf));
//关闭
fclose(pf);
pf = NULL;
return 0;
}
6、文件拷贝
知道文件的输入输出后,我们就可以写一个文件拷贝的代码
#define _CRT_SECURE_NO_WARNINGS #include7、二进制文件与文本文件#include #include int main() { FILE* pr = fopen("data1.txt", "r"); FILE* pw = fopen("data2.txt", "w"); if (NULL == pr) { printf("open file for reading :%s", strerror(errno)); return 0; } if (NULL == pw) { printf("open file for writing :%s", strerror(errno)); //读数据的文件指针已经打开,需要关闭 fclose(pr); pr = NULL; return 0; } char buf[1000] = { 0 }; while (fgets(buf, 1000, pr))//读文件 { //写文件 fputs(buf, pw); } //关闭 fclose(pw); fclose(pr); pw = NULL; pr = NULL; return 0; }
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换,以ASCII字符的形式存储的文件就是文本文件
8、文件读取结束的标志1、被错误使用的feof
feof函数的返回值直接用来判断文件是否结束,而是应用于当文件读取结束的时候,判断是读取失败结束,还是遇到文件尾结束
文本文件读取是否结束
fgetc判断是否为EOF
fgets判断是否为NULL
二进制文件的读取结束判断
fread的返回值是否小于实际要读的个数
#include9、文件缓冲区#include int main(void) { int c; // 注意:int,非char,要求处理EOF FILE* fp = fopen("test.txt", "r"); if (!fp) { perror("File opening failed"); return EXIT_FAILURE; } //fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF while ((c = fgetc(fp)) != EOF) // 标准C I/O读取文件循环 { putchar(c); //判断是什么原因结束的 if (ferror(fp)) puts("I/O error when reading"); else if (feof(fp)) puts("End of file reached successfully"); fclose(fp); }



