WHCSRL 技术网

文件 1.0

文件1.0

文件的详细介绍

引子

 文件.在我们前面学习通讯录时,程序运行起来时,可以给通讯录增删查改,但此时数据是存放在内存中,当程序退出时,通讯录的数据就消失了。
就很难受,为了使得数据持久化,我们就应该把数据存放在磁盘文件,存放到数据库等方式,磁盘上关机了重启还会在,使数据持久化,因此就需要用到文件

目录

文件

目录

文件

1.什么是文件 

2.文件名

3.文件指针(文件的打开与关闭)

4.文件的使用


1 什么是文件

在磁盘上所有的东西都是文件,c盘包括桌面的,
但一般在程序设计时,分两种:程序文件和数据文件(从文件的功能进行分类的)
程序文件有源程序文件.c,目标文件.obj,可执行文件.exe
数据文件,我们写的数据

 2.文件名

文件名,一个文件有唯一的文件标识。便于用户使用和识别(绝对路径)
文件名包含3个部分:文件路径+文件名主干+文件名后缀
如c:code est.txt,其中c:code是路径名,test叫文件主干名,.txt叫文件的后缀2

3.文件指针

4.文件指针(文件的打开与关闭)
每个被使用的文件都开辟了一个相应的文件信息区,用于存放文件的相关信息,
(如文件的名字,文件状态及文件当前的位置)这些信息都保持在一个结构体变量中,该结构体类型名叫FILE
一般用FILE型指针来维护FILE结构的变量,这样使用起来更加方便
FILE* pf,pf是指向FILE型的变量,可以使用pf来指向某个文件信息区,通过文件信息区中的信息就可以访问该文件,即可以通过文件指针变量找到与他相关的文件,

4.文件的使用

文件在读写之前首先要打开文件fopen,在文件使用完之后要关闭文件fclose,fopen返回失败会返回一个空指针,因此每次使用都要判断

其中fopen原型是FILE * fopen(const char * path, const char * mode);

const char * path是使用的路径,即要在哪个文件中使用

const char * mode是fopen的打开形式

常见的模式有”r“,(read)以只读方式打开文件,该文件必须存在。

”w“(write)打开只写文件,若文件存在则文件长度清为零,即该文件内容会消失;若文件不存在则创建该文件。

例如

1.0

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. int main()
  4. {
  5. FILE *pf=fopen("tst.dat", "w");*///"test.dat"是文件名,"w"是打开方式(以写的形式进行创建)(只写)“w”为了 输出数据,打开一个文件,如果指定文件不存在,就新建一个(在此文件中开辟)
  6. if (pf == NULL)
  7. {
  8. perror("fopen");
  9. return 1;
  10. }
  11. //写文件
  12. //关闭文件(不想要了)
  13. fclose(pf);
  14. pf = NULL;//可类比动态内存开辟,补不置成空指针就会报错
  15. return 0;
  16. }

1.1

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE *pf=fopen("D:\2021\class\test.7\test.dat", "w");//如果文件并不是在此文件下创建的化,同样也不会运行成功,但使用绝对路径是可以的
  5. //,单斜杠情况下会将后面理解为转义字符,因此都要使用双斜杠,用于将打印出来
  6. if (pf == NULL)
  7. {
  8. perror("fopen");
  9. return 1;
  10. }
  11. //写文件
  12. //关闭文件(不想要了)
  13. fclose(pf);
  14. pf = NULL;//
  15. return 0;
  16. }

1.3

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE *pf = fopen("tst.dat", "r");//以读的方式打开
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. //写文件
  11. //关闭文件(不想要了)
  12. fclose(pf);
  13. pf = NULL;//可类比动态内存开辟,
  14. return 0;
  15. }

文件的顺序读写 


:流,高度抽象的概念,,我们写的程序有时想放屏幕,硬盘,u盘,光盘,网络,程序要操作各种硬件,也就需要各种的读写方式,因此在程序与硬件中抽象出流这个层次
我们只有把数据放到流里面去,写文件可以理解为文件流,
c语言程序运行起来,就默认打开了3个流
stdin-标准输入流--键盘,  stdout标准输出流--屏幕, stderr--标准错误流--屏幕,类型都是FILE*的

 使用哪个流就在哪个流输出输入

代码2.0

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE *pf = fopen("test.dat", "w");//以w的形式打开,即使原来有内容也会清空掉,
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. //写文件
  11. fputc('b', pf);//文件字符输入,
  12. fputc('i', pf);
  13. fputc('t', pf);//便会向test.dat文件中输入bit
  14. // 关闭文件
  15. fclose(pf);
  16. pf = NULL;
  17. return 0;
  18. }

2.1 

  1. #include<stdio.h>
  2. int main()
  3. {
  4. fputc('c', stdout);//便在屏幕上打印了c这字符
  5. fputc('b', stdout);
  6. fputc('a', stdout);
  7. return 0;
  8. }

 2.2.

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE *pf = fopen("test.dat", "r");//以w的形式打开,即使原来有内容也会清空掉,
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. //读文件,fgetc从文件首字符中一个一个读取
  11. //int ret=fgetc(pf);//从文件流里面读一个字符,可以从文件,也可以从标准输入流中,文件字符输入,如果读取正常,会返回此字符的ascll值,如果读取失败,会返回EOF(-1)
  12. //printf("%%%%c", ret);
  13. //ret = fgetc(pf);
  14. //printf("%%%%c", ret);//读取的都是test.dat
  15. int ret = fgetc(stdin);//从标准屏幕输入流里面读一个字符,可以从文件,也可以从标准输入流中,文件字符输入,如果读取正常,会返回此字符的ascll值,如果读取失败,会返回EOF(-1)
  16. printf("%%%%c", ret);
  17. ret = fgetc(stdin);
  18. printf("%%%%c", ret);//读取的都是test.dat,文件结束就会输出EOF为-1
  19. fclose(pf);
  20. pf = NULL;
  21. return 0;
  22. }

我们不仅可以一个字符一个字符的输入与输出,

我们也可以一行一行的输入与输出

可以用到fgets,fputs

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE*pf = fopen("test.dat", "w");//以写的形式打开
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. //写文件-按行写
  11. fputs("abcdef ",pf);//s-string写字符串打个 就可以换行,pf是要写的文件流
  12. fputs("ghijk ", pf);
  13. //用完关闭文件
  14. fclose(pf);
  15. pf = NULL;
  16. return 0;
  17. }
  1. #include<stdio.h>
  2. int main()
  3. {
  4. char arr[10] = { 0 };
  5. FILE*pf = fopen("test.dat", "r");//以读的形式打开
  6. if (pf == NULL)
  7. {
  8. perror("fopen");
  9. return 1;
  10. }
  11. //读文件-按行读
  12. fgets(arr, 4, pf);//fgets(const char*string,const int n,const stream),n是可以读的最大字符,但多了一个n要+1
  13. printf("%%%%s ", arr);//读完从c后开始读
  14. fgets(arr, 4, pf);//最多读3个
  15. printf("%%%%s ", arr);
  16. //用完关闭文件
  17. fclose(pf);
  18. pf = NULL;
  19. return 0;
  20. }

我们接下来介绍一下fprintf,fscanf,sscanf,sprintf

  1. #include<stdio.h
  2. struct s
  3. {
  4. char age[10];
  5. int a;
  6. float f;
  7. };
  8. int main()
  9. {
  10. struct s a = { "hello",20,5.5f };
  11. char buf[100] = { 0 };
  12. struct s tmp = { 0 };
  13. //sprintf是把格式化的数据转化成字符串,
  14. sprintf(buf, "%%%%s %%%%d %%%%f", a.age, a.a, a.f);
  15. printf("%%%%s ", buf);
  16. //从buf这个字符串中还原出一个结构体
  17. //从字符串中读出格式化的数据
  18. sscanf(buf, "%%%%s %%%%d %%%%f", tmp.age, &tmp.a, &tmp.f);
  19. printf("%%%%s %%%%d %%%%f", tmp.age, tmp.a, tmp.f);
  20. return 0;
  21. }

fprintf(FILE *stream, const char *format,......)除去前面的流,后都和printf一样,

  1. struct a
  2. {
  3. char arr[10];
  4. int num;
  5. float sc;
  6. };
  7. int main()
  8. {
  9. struct a s = { "abcd",10,5.5f };
  10. FILE* pf = fopen("test.dat", "w");
  11. if (pf == NULL)
  12. {
  13. perror("fopen");
  14. return 1;
  15. }
  16. fprintf(pf, "%%%%s %%%%d %%%%f", s.arr, s.num, s.sc);//格式化输出,写入pf文件流,
  17. return 0;
  18. }

fscanf同scanf多了前面的流

  1. int main()
  2. {
  3. struct a s = { "abcd",10,5.5 };
  4. FILE* pf = fopen("test.dat", "r");
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. fscanf(pf, "%%%%s %%%%d %%%%f", s.arr, &(s.num), &(s.sc));//格式化输出,写入pf文件流
  11. printf("%%%%s %%%%d %%%%f", s.arr, s.num, s.sc);
  12. return 0;
  13. }

fwrite二进制输出 (const void *ptr, size_t size, size_t nmemb, FILE *stream)

把 ptr 所指向的数组中的数据写入到给定流 stream 中

size这是要被写入的每个元素的大小,以字节为单位

nmemb -- 这是元素的个数,每个元素的大小为 size 字节

  1. int main()
  2. {
  3. struct a s = { "abcd",10,5.5 };
  4. FILE* pf = fopen("test.dat", "w");
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. fwrite(&s, sizeof(struct a), 1, pf);//二进制输出,写入pf文件流
  11. fclose(pf);
  12. pf = NULL;
  13. return 0;
  14. }
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream) 

与fwrite等同二进制输出

  1. int main()
  2. {
  3. struct a s = { "abcd",10,5.5 };
  4. FILE* pf = fopen("test.dat", "r");
  5. if (pf == NULL)
  6. {
  7. perror("fopen");
  8. return 1;
  9. }
  10. fread(&s, sizeof(struct a), 1, pf);//二进制输入,读出pf文件流
  11. printf("%%%%s %%%%d %%%%f", s.arr, s.num, s.sc);
  12. fclose(pf);
  13. pf = NULL;
  14. return 0;
  15. }

推荐阅读