系列文章目录
前言
✅作者简介:大家好,我是橘橙黄又青,一个想要与大家独特提高的男人😉😉
🍎团体主页:橘橙黄又青_C言语,数据结构,函数-CSDN博客
目的:学习文件操作,即文件相关函数的学习
在这里首先搁置我团体以为好的学习c言语的网站
cplusplus.com: https://legacy.cplusplus.com/reference/clibrary/
好了咱们如今开局吧?
1. 为什么使⽤⽂件?
2. 什么是⽂件?
2.1 程序⽂件
2.2 数据⽂件
2.3 ⽂件名
3. ⼆进制⽂件和⽂本⽂件
#include <stdio.h>
int main()
{int a = 10000;FILE* pf = fopen("test.txt", "wb");fwrite(&a, 4, 1, pf);//⼆进制的方式写到⽂件中fclose(pf);pf = NULL;return 0;
}
4. ⽂件的关上和封锁
在此之前先了解一个形象的概念:
4.1 流和规范流
4.1.1 流
4.1.2 规范流
那为什么咱们从键盘输⼊数据,向屏幕上输入数据,并没有关上流呢?
stdin、stdout、stderr 三个流的类型是: FILE* ,理论称为 ⽂件指针 。
4.2 ⽂件指针
struct _iobuf {char *_ptr;int _cnt;char *_base;int _flag;int _file;int _charbuf;int _bufsiz;char *_tmpfname;};
typedef struct _iobuf FILE;
FILE* pf;//⽂件指针变量
4.3 ⽂件的关上和封锁
//关上⽂件
FILE * fopen ( const char * filename, const char * mode );//两个参数:一个是文件名,一个是文件经常使用方式
//封锁⽂件
int fclose ( FILE * stream );
⽂件使⽤⽅式
|
含意
|
假设指定⽂件不存在
|
“r”(只读)
|
为了输⼊数据,关上⼀个曾经存在的⽂本⽂件
|
出错
|
“w”(只写)
|
为了输入数据,关上⼀个⽂本⽂件
|
建⽴⼀个新的⽂件
|
“a”(追加)
|
向⽂本⽂件尾增加数据
|
建⽴⼀个新的⽂件
|
“rb”(只读)
|
为了输⼊数据,关上⼀个⼆进制⽂件
|
出错
|
“wb”(只写)
|
为了输入数据,关上⼀个⼆进制⽂件
|
建⽴⼀个新的⽂件
|
“ab”(追加)
|
向⼀个⼆进制⽂件尾增加数据
|
建⽴⼀个新的⽂件
|
“r+”(读写)
|
为了读和写,关上⼀个⽂本⽂件
|
出错
|
“w+”(读写)
|
为了读和写,倡导⼀个新的⽂件
|
建⽴⼀个新的⽂件
|
“a+”(读写)
|
关上⼀个⽂件,在⽂件尾进⾏读写
|
建⽴⼀个新的⽂件
|
“rb+”(读写)
|
为了读和写关上⼀个⼆进制⽂件
|
出错
|
“wb+”(读
写)
|
为了读和写,新建⼀个新的⼆进制⽂件
|
建⽴⼀个新的⽂件
|
“ab+”(读
写)
|
关上⼀个⼆进制⽂件,在⽂件尾进⾏读和写
|
建⽴⼀个新的⽂
|
咱们怎样了解 读和写看图:
这里咱们展示一下关上封锁,实战代码:
/* fopen fclose example */
#include <stdio.h>
int main ()
{FILE * pFile;//关上⽂件pFile = fopen ("myfile.txt","w");//⽂件操作if (pFile!=NULL){fputs ("fopen example",pFile);//封锁⽂件fclose (pFile);}return 0;
}
5. ⽂件的顺序读写
5.1 顺序读写函数引见
函数名
|
配置
|
适⽤于
|
fgetc
|
字符输⼊函数
|
一切输入流
|
fputc
|
字符输入函数
|
一切输入流
|
fgets
|
⽂本⾏输⼊函数
|
一切输入流
|
fputs
|
⽂本⾏输入函数
|
一切输入流
|
fscanf
|
格局化输⼊函数
|
一切输入流
|
fprintf
|
格局化输入函数
|
一切输入流
|
fread
|
⼆进制输⼊
|
⽂件
|
fwrite
|
⼆进制输入
|
⽂件
|
那好咱们来一个一个引见:关上网站:
https://legacy.cplusplus.com/reference/clibrary/
(1) fputc
参数是:文件名和流
代码成功:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "w");//写入文件if (pf == NULL){perror("fopen");return 1;}fputc('a', pf);//写入一个字符'a'fputc('\n', pf);fputc('b', pf);fclose(pf);return 0;
}
fputc只能一个一个字符的输入,也可以写一个循环输入多个字符。
for (i = 0; i < 26; i++) {fputc('a' + 1, pf);fputc('\n', pf);//写完换行}
(2)
fgetc
如今先咱们输入字符进“data.txt”文件中,比如说输入:“abcdefg",而后实现代码读操作
代码:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "r");//写入文件if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);//读取一个字符printf("%c", ch);//打印fclose(pf);pf = NULL;return 0;
}
详细操作和输入结果如下:
当然也可以写成循环的方式,然而要留意什么时刻完结,比如说:
上方代码:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "r");//写入文件if (pf == NULL){perror("fopen");return 1;}int ch = 0;while ((ch = fgetc(pf)) != ' ') {printf("%c", ch);//打印}fclose(pf);pf = NULL;return 0;
}
两种状况:
这就要看文件文本句末了,防止形成死循环。
接上去咱们学习一个复制文件内容的操作:
假定文件外面有代码
代码成功:
//从data.txt中读取数据
//写到data2.txt的文件中#define _CRT_SECURE_NO_WARNINGS#include<stdio.h>
#include<math.h>int main()
{FILE* pfread = fopen("data.txt", "r");//读if (pfread == NULL){perror("fopen->data1.txt");//报错详细一点return 1;}FILE* pfwrite = fopen("data2.txt", "w");//写if (pfwrite == NULL){fclose(pfread);//假设产生失误先封锁关上文件pfread = NULL;perror("fopen->data2.txt");return 1;}//数据的读写(拷贝)int ch = 0;while ((ch = fgetc(pfread)) != EOF){fputc(ch, pfwrite);//把ch写入pfwrite}fclose(pfread);fclose(pfwrite);return 0;
}
输入结果:
(3)fputs
代码成功:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "w");if (pf == NULL){return 1;}//写文件 - 写一行fputs("abcdef\n", pf);fputs("abcdef\n", pf);fputs("abcdef\n", pf);fputs("abcdef\n", pf);fclose(pf);pf = NULL;return 0;
}
输入结果:
(4)fgets
三个参数:
1. 输上天的指针
2.输入个数,然而要-1由于最后要输入\0
3.流
代码成功:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){return 1;}//读取char arr[20] = "xxxxxxxxxxxxxxx";fgets(arr, 10, pf);//从流中读取9个字符(有一个放入\0)放入arr中fclose(pf);pf = NULL;return 0;
}
输入结果:
当然也可以输入到屏幕上:
看代码:
#include<stdio.h>
#include<math.h>int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){return 1;}//读取char arr[20] = "xxxxxxxxxxxxxxx";fgets(arr, 10, stdin);//规范输入流fputs(arr, stdout);//规范输入流fclose(pf);pf = NULL;return 0;
}
输入结果:
这里要留意的是输入流和输入流在函数的位置。
(5) fscanf和fprintf
fprintf代码成功:
#include<stdio.h>
#include<math.h>
struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s = { "zhangsan", 20, 90.5f };FILE*pf = fopen("data.txt", "w");if (pf == NULL){return 1;}//写文件//printf(""%s %d %.1f", s.name, s.age, s.score");//很相似fprintf(pf, "%s %d %.1f", s.name, s.age, s.score);//fclose(pf);pf = NULL;return 0;
}
输入结果:
同理:fscanf
假定文件里有:
代码:
#include<stdio.h>
#include<math.h>
struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s = {0};FILE* pf = fopen("data.txt", "r");//读if (pf == NULL){return 1;}//写读文件fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));fprintf(stdout, "%s %d %.1f\n", s.name, s.age, s.score);//输入屏幕//fclose(pf);pf = NULL;return 0;
}
输入结果:
6. fwrite二进制输入
首先咱们先来学习一下这个函数:
代码成功:
#include<stdio.h>
#include<math.h>struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s = {"zhangsan", 20, 90.5};FILE* pf = fopen("data.txt", "wb");//wb是以二进制的方式写入if (pf == NULL){return 1;}//二进制的方式写文件fwrite(&s, sizeof(s), 1, pf);fclose(pf);pf = NULL;return 0;
}
输入:
这里是以二进制输入的文本翻译成这样,是由于文本不具有二进制翻译,然而假设以二进制输入是和输入一样的结果,上方咱们把刚刚以二进制输入文件以二进制输入看看。
7. fread以二进制输入
这里咱们可以看到,参数和上方的fwite是一样的。
代码成功:
#include<stdio.h>
#include<math.h>struct Stu
{char name[20];int age;float score;
};int main()
{struct Stu s = {0};FILE* pf = fopen("data.txt", "rb");//rb以二进制方式读进if (pf == NULL){return 1;}//二进制的方式du文件fread(&s, sizeof(s), 1, pf);printf("%s %d %lf", s.name , s.age, s.score );fclose(pf);pf = NULL;return 0;
}
输入结果:
在这里咱们在意识两个函数sscanf和sprintf.
8.sscanf和sprintf.
对比:
经常使用:
#include <stdio.h>struct S
{char name[20];int age;float score;
};int main()
{struct S s = { "zhangsan", 20, 85.5f };struct S tmp = { 0 };char arr[100] = { 0 };sprintf(arr, "%s %d %f", s.name, s.age, s.score);//把结构体s的数据输入arrprintf("%s\n", arr);//sscanf(arr, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));//把arr结构体数据输入tmpprintf("%s %d %f\n", tmp.name, tmp.age, tmp.score);return 0;
}
这里要缓缓了解,
6. ⽂件的随机读写
6.1 fseek和ftell
依据⽂件指针的位置和偏移量来定位⽂件指针。
什么意思,来
6.2 ftell
前往⽂件指针相关于起始位置的偏移量。
函数内容:
long int ftell ( FILE * stream );
如今咱们来成功 fseek和ftell
代码展现:
#include <stdio.h>int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);//让光标指向dint n = ftell(pf);//计算相对起始位置的偏移量并保留printf("%d\n", n);fclose(pf);pf = NULL;return 0;
}
输入结果:
再看看
这个:
#include <stdio.h>int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);//让光标指向dint n = ftell(pf);//计算相对起始位置的偏移量并保留printf("%d\n", n);fseek(pf, -4, SEEK_CUR);//以后位置printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}
输入结果:
怎样了解:
6.3 rewind
作用:让⽂件指针的位置回到⽂件的起始位置
代码展现:
#include <stdio.h>
//data.txt外面有abcdefg
int main()
{FILE* pf = fopen("data.txt", "r");if (pf == NULL){perror("fopen");return 1;}int ch = fgetc(pf);printf("%c\n", ch);ch = fgetc(pf);printf("%c\n", ch);//光标指向crewind(pf);//让⽂件指针的位置回到⽂件的起始位置ch = fgetc(pf);printf("%c\n", ch);fclose(pf);pf = NULL;return 0;
}
输入结果:
7. ⽂件读取完结的判定
7.1 被失误使⽤的 feof
#include <stdio.h>
#include <stdlib.h>
int main(void)
{int c; // 留意:int,⾮char,要求处置EOFFILE* fp = fopen("test.txt", "r");if (!fp) {perror("File opening failed");return EXIT_FAILURE;//1}//fgetc 当读取失败的时刻或许遇到⽂件完结的时刻,都会前往EOFwhile ((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);
}
#include <stdio.h>
enum { SIZE = 5 };
int main(void)
{double a[SIZE] = { 1.,2.,3.,4.,5. };FILE* fp = fopen("test.bin", "wb"); // 必定⽤⼆进制形式fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组fclose(fp);double b[SIZE];fp = fopen("test.bin", "rb");size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组if (ret_code == SIZE) {//判别前往值能否⼩于实践要读的个数puts("Array read successfully, contents: ");for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);putchar('\n');}else { // error handlingif (feof(fp))//yudao文末完结printf("Error reading test.bin: unexpected end of file\n");else if (ferror(fp)) {//遇到失误完结perror("Error reading test.bin");}}fclose(fp);
}
8. ⽂件缓冲区
#include <stdio.h>
#include <windows.h>
//VS2019 WIN11环境测试
int main()
{FILE* pf = fopen("test.txt", "w");fputs("abcdef", pf);//先将代码放在输入缓冲区printf("睡眠10秒-曾经写数据了,关上test.txt⽂件,发现⽂件没有内容\n");Sleep(10000);printf("刷新缓冲区\n");fflush(pf);//刷新缓冲区时,才将输入缓冲区的数据写到⽂件(磁盘)//注:fflush 在⾼版本的VS上不能使⽤了printf("再睡眠10秒-此时,再次关上test.txt⽂件,⽂件有内容了\n");Sleep(10000);fclose(pf);//注:fclose在封锁⽂件的时刻,也会刷新缓冲区pf = NULL;return 0;
}