目录
前言:
文件的分类
1. 程序文件
2.数据文件
文件的使用
文件指针
文件指针的使用
文件的打开与关闭
文件的使用方式
示例1:
示例2:
文件的顺序读写
函数简介
示例1:
示例2:
函数简介
示例1:
示例2:
函数简介
示例1:
示例2:
函数简介:
示例1:
示例2:
文件的随机读写
函数简介
示例:
函数简介
示例:
函数简介:
示例:
文件读取结束的判定
函数简介:
函数简介:
示例(文本文件):
前言:
当我们编写某个程序时,程序中的信息存放于内存当中,当程序退出后,再次运行,又得重新输入数据,这就涉及到数据持久化的问题,我们一般数据持久化的方法有将数据存放于电脑的磁盘上,就可以做到数据的持久化。以计算机硬盘为载体储存在计算机上的信息集合即为文件,文件最主要的作用便是保存数据。
文件的分类
1. 程序文件
包括源程序文件(后缀为.c) 目标文件(windows环境后缀.obj)
可执行程序文件(windows环境后缀为.exe)
2.数据文件
存储程序运行时读写的数据的文件,本篇只讨论数据文件
文件的使用
文件的操作一般由三步组成:
1. 打开文件 2. 读文件/写文件 3. 关闭文件
注: c语言程序运行时,默认打开标准输入流(stdin), 标准输出流(stdout) , 标准错误流( stderr);
文件指针
每个被使用的文件,都在内存中开辟了一块相应的文件信息区,用来存放文件的相关信息(例如文件名 文件状态 文件当前的位置),这些信息保存到一个结构体变量中,该结构体由系统申明,取名为FILE。
struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE;
文件指针的使用
每当打开一个文件时,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,一般都是通过一个FILE的指针来维护FILE结构的变量,每次打开文件时,系统会将文件指针放在文件的开头。
FILE* pf;//pf为文件指针变量//pf指向某个文件的文件信息区,通过文件信息区可以访问该文件//即通过文件指针变量能够找到与之关联的文件
文件的打开与关闭
ANSIC规定使用fopen()函数打开文件,使用fclose()函数关闭文件
函数功能:当使用fopen()打开某个文件,若文件打开成功,系统主动创立文件信息区,同时返回文件信息区的起始地址;若文件打开失败,返回NULL;
参数解读:
const char* filename 打开文件的文件名 const char* mode 打开文件的方式,常用的打开方式有 "r"(只读) "w"(只写) "a"(追加)
函数功能:fclose()函数用来关闭当前文件流,文件成功关闭,返回0;文件关闭失败,返回 EOF;
tips: 使用fclose()函数关闭文件,还应该释放文件指针
文件的使用方式
以"w"的方式打开文件,若文件存在,会将文件的内容进行销毁,若文件不存在,建立一个新的文件;
示例1:
# include <stdio.h>
int main()
{FILE* pf = fopen("data.txt", "r");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,以只读的方式使用//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
示例2:
int main()
{//在桌面上创建test.txt需要绝对路径下的文本文件名,并且为防止转义字符加上\FILE* pf = fopen("C:\\Users\\Administrator\\Desktop\\test.txt", "w");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,以只写的方式使用//关闭文件fclose(pf);pf = NULL;return 0;
}
文件的顺序读写
函数简介
函数功能:从指定的文件流中读取一个字符,读取成功返回读取到字符的ASCII码值,读取到文件末尾或读取失败返回EOF
函数功能:向指定的文件写入一个字符,character为要写入的字符,stream为文件指针,写入成功时返回字符的ASCII码值,写入失败时返回EOF
示例1:
# include <stdio.h>
int main()
{FILE* pf = fopen("test.txt", "w");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,写文件fputc('a', pf);fputc('b', pf);fputc('c', pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
结果阐述:
1.文件内部有一个位置指针,用来指向当前读写到的位置,也就是读写到第几个字节;
2.当文件打开时,位置指针总是指向文件的第一个字节,每写入一个字符,文件内部的位置3指针向后移动一个字节;
3.位置指针只是一个标志,表示文件读写到的位置,并不表示地址,由系统自动设置,对用户隐藏;
示例2:
int main()
{FILE* pf = fopen("test.txt", "r");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,读文件int ch=fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
函数简介
函数功能:从stream流中读取num-1个字符存储到字符指针变量str所指向的内存空间,遇到EOF或者'\n'停止读取,并且会将'\n'也一并读取到str所对应的缓冲区中,读取成功返回str的地址,读取失败返回NULL
当num小于字符串长度时,字符串将会被截取
当num大于字符串长度时,多余部分自动用'\0' 填充
num由num-1个字符加上'\n'组成,即最后一个字符自动加上换行符;
函数功能:
将str中的字符串写入到stream流中,但不包括'\0' ,写入成功返回大于0的数,写入失败返会EOF
示例1:
int main()
{FILE* pf = fopen("test.txt", "w");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,写文件 - 写一行//fputs()函数只负责写入一行,并不会自动换行fputs("abcdef\n", pf);fputs("b\0it", pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
示例2:
int main()
{FILE* pf = fopen("test.txt", "r");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,读文件 - 读一行char arr[10] = { 0 };fgets(arr, 10, pf);printf("%s\n", arr);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
函数简介
函数功能:
根据数据格式const char* format,从流中读取数据存储到 [...] 的参数中;即从流中读取格式化数据;返回值有三种情况,分别为正整数,0,EOF;如果读取成功,返回实际读取的参数个数;如果读取失败,返回0;如果遇到文件末尾或读取格式错误的情况下,返回EOF;
函数功能:
scanf第一个参数为输入格式控制符,scanf的后续参数是格式转换完成后,数据的存储位置
如果scanf将转换后的二进制存储到基本变量中,变量名前加&操作符;
如果scanf()函数将字符串存储到字符数组中,字符数组名不用加&操作符;
函数功能:
函数第一个参数为存储数据的位置,第二个参数为格式控制字符串,sscanf函数会从s里读取数据,依照format的格式将数据写入到 [...]数据的存储位置;即将字符串转换为具有一定格式的数据;
结论:
scanf函数从标准输入流(stdin)中读取数据,而fscanf函数适用于所有输入流,可以将数据从自定义的流(stream)中读取出来,不仅仅局限于标准输入流
函数功能:
fprintf函数根据指定的格式(format) ,向输出流(stream)写入数据[...],fprintf()函数的返回值为打印的字符的个数;
函数功能:
向标准输出设备按规定格式输出信息
函数功能:
将具有一定格式的数据转换为字符串;
结论:printf函数打印数据到标准输出流(stdout),而fprintf()函数适用于所有输出流,可以将数据写到自定义的流中,不仅仅局限于标准输出流;
示例1:
struct s
{int a;float b;
};
int main()
{FILE* pf = fopen("test.txt", "w");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,写文件struct s s1 = { 100, 3.14f };fprintf(pf, "%d %f", s1.a, s1.b);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
示例2:
struct s
{int a;float b;
};
int main()
{FILE* pf = fopen("test.txt", "r");//判断打开文件是否成功if (pf == NULL){perror("fopen");return 1;}//文件打开成功,读文件struct s s1 = { 0 };fscanf(pf, "%d %f", &(s1.a), &(s1.b));printf("%d %f", s1.a, s1.b);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
函数简介:
函数功能:
从文件中读取若干个字节数据到内存的缓冲区中
void* ptr:将文件中的二进制数据读取到该缓冲区中;
size_t size:读取的基本单元的大小,单位是字节,一般为ptr缓冲单位大小;
- 如果ptr缓冲区是char类型数组,则该参数的值是sizeof(char)
- 如果ptr缓冲区是int类型数组,则该参数的值是sizeof(int)
size_t count :读取的基本单元的个数
FILE* stream : 文件指针
fread函数的返回值为实际从文件中读取的 基本单元的个数;读取的字节数=基本单元数*基本单元字节的大小;
函数功能:
const void *ptr : 指针指向的数据的内存首地址 ;数据来自ptr
size_t size : 要写出数据的 基本单元 的字节大小 , 写出单位的大小 ;
size_t count : 要写出数据的 基本单元 的个数 ;
FILE *stream : 打开的文件指针 ;
返回值为实际写入到文件的基本单元的个数
示例1:
struct S
{int a;float b;char arr[10];
};
int main()
{struct S s1 = { 100, 3.14f, "abc" };//以二进制写入的形式打开文件FILE* pf = fopen("data.txt", "wb");if (pf == NULL){perror("fopen");return 1;}//写文件fwrite(&s1, sizeof(struct S), 1, pf);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果(二进制文件):
示例2:
struct S
{int a;float b;char arr[10];
};
int main()
{struct S s1 = { 0 };//以二进制读取的形式打开文件FILE* pf = fopen("data.txt", "rb");if (pf == NULL){perror("fopen");return 1;}//读文件fread(&s1, sizeof(struct S), 1, pf);printf("%d %f %s\n", s1.a, s1.b, s1.arr);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
文件的随机读写
文件的随机读写指的是从指定的位置进行读写操作;
函数简介
函数功能:
fseek函数设置文件指针stream的位置,如果执行成功,文件指针将指向以origin为基准,偏移offset个字节的位置;若执行失败,则不改变stream指向的位置;当文件指针定位成功时返回0,否则返回其他值;
第一个参数为文件指针
第二个参数offset为偏移量,正数表示正向偏移,负数表示负向偏移
第三个参数origin设定从文件的那个位置开始偏移,c语言规定起始位置有3种,分别为文件开头,当前位置,文件末尾;
起始点 | 常量名 | 常量值 |
---|---|---|
文件开头 | SEEK_SET | 0 |
当前位置 | SEEK_CUR | 1 |
文件末尾 | SEEK_END | 2 |
注:每使用完一次 fseek函数,文件指针自动向后移动一位
示例:
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件//定位文件指针到f的位置fseek(pf, 5, SEEK_SET);int ch = fgetc(pf);printf("%c\n", ch);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
函数简介
函数功能:
获取文件的 当前指针位置 相对于 文件起始地址的偏移字节数
示例:
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件//定位文件指针到f的位置int ch = fgetc(pf);printf("%c\n", ch);//ach = fgetc(pf);printf("%c\n", ch);//bch = fgetc(pf);printf("%c\n", ch);//cint pos = ftell(pf);printf("%d\n", pos);//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
函数简介:
函数功能:
将文件内部的位置指针重新指向一个流(数据流/ 文件流)的起始位置
示例:
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}//读文件//定位文件指针到f的位置int ch = fgetc(pf);printf("%c\n", ch);//ach = fgetc(pf);printf("%c\n", ch);//brewind(pf);//让文件内部的位置指针回到起始位置ch = fgetc(pf);printf("%c\n", ch);//a//关闭文件fclose(pf);pf = NULL;return 0;
}
运行结果:
文件读取结束的判定
函数简介:
函数功能:
当文件读取结束时,判断读取结束的原因是否是遇到文件末尾结束;没有到达文件末尾,返回0;到达文件末尾,返回非0值;
注:在文件读取的过程中,不能使用feof函数的返回值判断文件是否读取结束;
那么如何判断一个文件读取结束呢?
1. 文本文件读取是否结束,判断返回值是否为EOF或者NULL
- fgetc判断是否为EOF
- fgets判断返回值是否为NULL
2. 二进制文件的读取结束判断返回值是否小于实际要读的个数
- fread判断返回值是否小于要读的个数;
函数简介:
函数功能:
当文件读取结束时,判断是否遇到错误读取结束,无错误出现时返回0,有错误出现时返回非0;
示例(文本文件):
int main()
{FILE* pf = fopen("test.txt", "r");if (pf == NULL){perror("File opening failed");return 1;}//fgetc当读取失败或者遇到文件结束时,都会返回EOFint c;while ((c = fgetc(pf)) != EOF){putchar(c);//正常读取}printf("\n");//读取结束//判断什么原因读取结束if (ferror(pf)){printf("I/O error when reading\n");}else if (feof(pf)){printf("End of File reached successfully\n");}return 0;
}
运行结果: