十二、文件操作
12.1 文件类型
12.2文件缓冲区![](https://i-blog.csdnimg.cn/blog_migrate/9e014a6c65ff7765008c99af5754058a.png)
12.3 打开和关闭文件
用fopen打开文件,格式如下:
FILE * fopen ( const char * filename, const char * mode );
filename是打开的文件名,有两种写法 :
1.相对路径:相对当前.c文件的路径
和当前.c文件在同一文件夹里的文件直接写文件名
FILE* fp = fopen("test.txt", "w");
在当前.c文件的上一级的文件夹里的文件,前面加上../
FILE* fp = fopen("../test.txt", "w");
2.绝对路径:完整的文件路径
FILE* fp = fopen("D:\\VS2020\\vscode\\动态内存\\动态内存\\test.txt", "w");
注意要在每个\前多加一个\,一个\会认为是转义字符
参数mode可取值:
”w“模式不论是否已经存在文件,都会重新建一个新文件出来
用fclose关闭文件
void main()
{
FILE* fp = fopen("D:\\VS2020\\vscode\\动态内存\\动态内存\\test.txt", "w");
if (fp == NULL)
{
printf("打开失败");
}
fclose(fp);
}
12.4文件的读取和写入
上面表格中的输入输出流包括文件和标准输入输出流,这里主要说一下标准输入输出流
键盘和屏幕就是所谓的标准输入流(stdin)和标准输出流(stdout),它们是自动打开的,不需要别的操作。输入流选择stdin就是从键盘输入字符,输出流选择stdout则是把内容打印在屏幕上
12.4.1 字符输入输出fputc和fgetc
int fputc ( int character, FILE * stream );
fputc:向输出流写入一个字符,第一个参数是int类型,输入时会自动转为ASCII码值存储在内存中
写入成功返回写入的字符,失败返回EOF
int fgetc ( FILE * stream );
fgetc:从输入流读一个字符,读取成功返回读到的字符,读取失败返回EOF
12.4.2 字符串输入输出fputs和fgets
int fputs ( const char * str, FILE * stream );
fputs:向输出流写字符串,字符串从函数的第一个参数地址(即要写的字符串地址)开始,到'\0‘结束,'\0'不会放到输出流中。和put函数不同的是,put会自动地在输出字符串末尾加一个换行符(无论字符串是否已经带有换行符),但fputs不会带任何别的字符
返回值:成功返回一个非0的数,失败返回EOF
char * fgets ( char * str, int num, FILE * stream );
fgets:从输入流中获取指定个数地字符,存到指定位置。str是存放从输入流获得的字符的内存空间指针(一般是数组),num是获取指定个数输入流字符,steam是输入流。
返回值:成功返回str,失败或者读取到文件结尾返回空指针
函数使用规则:
1.fgets函数会在获取字符的末尾自动添加一个'\0'字符,意味着如果参数num=10,只能从输入流stream中获得9个字符,最后一个字符是'\0'。如果输入流字符最后带有'\n',也会把'\n'传过去,并在'\n'后加'\0'
2.num不能超过str指向的数组空间大小
3.fgets在读取到'\n',(输入流里的字符<n时)读完字符串或者(输入流里的字符>=n时)读取到n-1个字符时结束
4.使用一次fgets后文件指针会停留在读取结束的位置,下一次读取时会从上一次结束的地方开始
12.4.3指定流的位置输入输出数据fscanf和fprintf
int fscanf ( FILE * stream, const char * format, ... );
fscanf:向指定输入流输入指定格式的数据
int fprintf ( FILE * stream, const char * format, ... );
fprintf:向指定输出流输出指定格式的数据 ,和printf类似,但printf输出流默认时stdout
struct Stu
{
int a;
float b;
char c[10];
};
struct Stu ss = { 0 };
void main()
{
struct Stu s = { 10,3.141,"ccccc" };
struct Stu ss={0};
FILE* fp = fopen("test.txt", "w+");
if (fp != NULL)
{
fprintf(fp, "%d %.2f %s", s.a, s.b, s.c);
rewind(fp);
fscanf(fp, "%d %f %s", &ss.a, &ss.b, ss.c);
}
printf("%d %f %s", ss.a,ss.b,ss.c);
fclose(fp);
}
12.4.4 字符串与格式化数据转换输入输出sscanf和sprintf
12.4.5二进制读写数据函数fread和fwrite
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
fread:以二进制形式读文件
ptr—存放读出来的二进制数据的内存地址(可以是数组指针、结构体指针)
size—每个元素所占字节个数
count—元素个数
stream—文件名称
返回值:返回读取到的元素个数,如果返回的个数小于参数里的count,可能时发生读错误,也可能是读到文件尾的EOF,可以用ferror和feof来判断,也可以通过比较返回数与count的大小判断是否读完文件
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );
fread:以二进制形式写文件
ptr—写数据存放的地址(可以是数组指针)
size—每个元素所占字节个数
count—元素个数
stream—目标文件名称
返回值:返回成功写的元素个数,如果返回的个数小于参数里的count,可能发生写错误,可以用ferror;可以通过比较返回数与count的大小判断是否读完文件
12.4.6设置文件指针到某个位置(读取文件中任意位置的数据)fseek
int fseek ( FILE * stream, long int offset, int origin );
fseek:设置文件指针位置
stream—操作文件名
offset—1.如果是二进制文件,offset是从起始位置开始偏移的字节数;2.如果是文本文件,offset要么是0(即从设置的起始位置开始),要么是通过ftell获得的数
origin—
12.4.7返回文件指针相对起始位置的偏移量ftell
long int ftell ( FILE * stream );
ftell—获得当前文件位置指针的位置
返回值:二进制文件返回的是偏离开头位置的字节数,文本文件返回值可能没有意义,但可以用于保存目前指示器位置,对文件操作后用于fseek函数将指示器返回到初始位置。失败的话返回-1
12.4.8 将文件指针重新返回到文件开头rewind
void rewind ( FILE * stream );
12.4.9 feof,ferror perror strerror
int feof ( FILE * stream );
feof:判断文件结束是否是因为遇到EOF,是的话返回非0值,不是返回0