• C【文件操作】


    1. 什么是文件

    磁盘上的文件是文件。 但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。

    1.1 程序文件

    包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境 后缀为.exe)。

    1.2 数据文件

    文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件。

    1.3 文件名

    1.4 文件缓冲区

    2. 文件的打开和关闭

    2 .1 文件指针:FILE

    缓冲文件系统中,关键的概念是“文件类型指针”,简称“文件指针”。

    每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名 字,文件状态及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是有系统 声明的,取名FILE.

    一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

    下面我们可以创建一个FILE*的指针变量:

    FILE* pf;//文件指针变量

    3.2 文件的打开(fopen)和关闭(fclose)

    文件在读写之前应该先打开文件,在使用结束之后应该关闭文件。

    在编写程序的时候,在打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指 针和文件的关系。

    ANSIC 规定使用fopen函数来打开文件,fclose来关闭文件

    //打开文件

    FILE * fopen ( const char * filename, const char * mode );

    //关闭文件

    int fclose ( FILE * stream ); 比特

    1. #include
    2. #include
    3. int main()
    4. {
    5. //打开文件test.txt
    6. //相对路径
    7. //.. 表示上一级路径
    8. //. 表示当前路径
    9. //fopen("../../test.txt", "r")
    10. //fopen("test.txt", "r");
    11. //绝对路径的写法【添加转义字符】
    12. //fopen("C:\\2020_code\\84班\\test_5_6\\test_5_6\\test.txt", "r");
    13. FILE* pf = fopen("test.txt", "w");
    14. if(pf == NULL)
    15. {
    16. printf("%s\n", strerror(errno));
    17. return 0;
    18. }
    19. //打开成功
    20. //读文件
    21. //关闭文件
    22. fclose(pf);
    23. pf = NULL;
    24. return 0;
    25. }

    3. 文件的顺序读写

    3.1 fputc:写入文件

    操作一行

    1. int main()
    2. {
    3. FILE* pfWrite = fopen("TEST.txt", "w");
    4. if(pfWrite == NULL)
    5. {
    6. printf("%s\n", strerror(errno));
    7. return 0;
    8. }
    9. //写文件
    10. fputc('b', pfWrite);
    11. fputc('i', pfWrite);
    12. fputc('t', pfWrite);
    13. //关闭文件
    14. fclose(pfWrite);
    15. pfWrite = NULL;
    16. return 0;
    17. }

    3.2 fgetc():读取文件

    操作一行

    1. int main()
    2. {
    3. FILE* pfRead = fopen("test.txt", "r");
    4. if(pfRead == NULL)
    5. {
    6. printf("%s\n", strerror(errno));
    7. return 0;
    8. }
    9. //读文件
    10. printf("%c", fgetc(pfRead));//b
    11. printf("%c", fgetc(pfRead));//i
    12. printf("%c", fgetc(pfRead));//t
    13. //关闭文件
    14. fclose(pfRead);
    15. pfRead = NULL;
    16. return 0;
    17. }

    3.3 输入/输出设备

    从键盘输入
    输出到屏幕.
    键盘&屏幕都是外部设备【默认打开的】

    键盘-标准输入设备- stdin
    屏幕-标准输出设备- stdout
    是一个程序默认打开的两个流设备

    stdin FILE*
    stdout FILE*
    stderr FILE*

    1. int main()
    2. {
    3. int ch = fgetc(stdin);
    4. fputc(ch, stdout);
    5. return 0;
    6. }

    3.4 fgets():读取文件存储到指定位置

    操作多行

    1. int main()
    2. {
    3. char buf[1024] = { 0 };
    4. FILE* pf = fopen("test.txt", "r");
    5. if (pf == NULL)
    6. {
    7. return 0;
    8. }
    9. //读文件
    10. //表示从pf输入流中读取1024个字节到buf中
    11. fgets(buf, 1024, pf);
    12. printf("%s", buf);//bit
    13. return 0;
    14. }

    3.5 fputs()

    要手动换行

    1. int main()
    2. {
    3. char buf[1024] = { 0 };
    4. FILE* pf = fopen("test.txt", "w");
    5. if (pf == NULL)
    6. {
    7. return 0;
    8. }
    9. //写文件
    10. fputs("hello\n", pf);
    11. fputs("world\n", pf);
    12. fclose(pf);
    13. pf = NULL;
    14. return 0;
    15. }

    3.6 fputs()与fgets()

    1. int main()
    2. {
    3. //从键盘读取一行文本信息
    4. //char buf[1024] = {0};
    5. fgets(buf, 1024, stdin);//从标准输入流读取
    6. fputs(buf, stdout);//输出到标准输出流
    7. //gets(buf);
    8. //puts(buf);
    9. return 0;
    10. }

    3.7 puts()

    会自动换行

    3.8 fprintf()

    1. struct S
    2. {
    3. int n;
    4. float score;
    5. char arr[10];
    6. };
    7. int main()
    8. {
    9. struct S s = { 100, 3.14f, "bit" };
    10. FILE* pf = fopen("test.txt", "w");
    11. if (pf == NULL)
    12. {
    13. return 0;
    14. }
    15. //格式化的形式写文件
    16. fprintf(pf, "%d %f %s", s.n, s.score, s.arr);
    17. fclose(pf);
    18. pf = NULL;
    19. return 0;
    20. }

    3.9 fscanf()

    1. struct S
    2. {
    3. int n;
    4. float score;
    5. char arr[10];
    6. };
    7. int main()
    8. {
    9. struct S s = {0};
    10. FILE* pf = fopen("test.txt", "r");
    11. if (pf == NULL)
    12. {
    13. return 0;
    14. }
    15. //格式化的输入数据
    16. fscanf(pf, "%d %f %s", &(s.n), &(s.score), s.arr);
    17. printf("%d %f %s\n", s.n, s.score, s.arr);
    18. fclose(pf);
    19. pf = NULL;
    20. return 0;
    21. }

    3.10 fscanf()和fprintf()

    1. struct S
    2. {
    3. int n;
    4. float score;
    5. char arr[10];
    6. };
    7. int main()
    8. {
    9. struct S s = { 0 };
    10. fscanf(stdin, "%d %f %s", &(s.n), &(s.score), s.arr);
    11. fprintf(stdout, "%d %.2f %s", s.n, s.score, s.arr);
    12. return 0;
    13. }

     

    3.11 面试题

    1. int main()
    2. {
    3. struct S s = { 100, 3.14f, "abcdef" };
    4. struct S tmp = {0};
    5. char buf[1024] = { 0 };
    6. //把格式化的数据转换成字符串存储到buf
    7. sprintf(buf, "%d %f %s", s.n, s.score, s.arr);
    8. //printf("%s\n", buf);
    9. //从buf中读取格式化的数据到tmp中
    10. sscanf(buf, "%d %f %s", &(tmp.n), &(tmp.score), tmp.arr);
    11. printf("%d %f %s\n", tmp.n, tmp.score, tmp.arr);
    12. return 0;
    13. }

    3.12 fwrite():写入二进制

    1. //fwrite:将数据以二进制的形式写入
    2. int main()
    3. {
    4. struct S s = { "张三", 20, 55.6 };
    5. FILE* pf = fopen("test.txt", "rb");
    6. if (pf == NULL)
    7. {
    8. return 0;
    9. }
    10. //二进制的形式都文件
    11. //表示将s中的数据写入到pf中
    12. fwrite(&s, sizeof(struct S), 1, pf);
    13. printf("%s %d %lf\n", &s.name, &s.age, &s.score);
    14. fclose(pf);
    15. pf = NULL;
    16. return 0;
    17. }

    3.13 fread:通过二进制的方式读出数据

    1. //fread:通过二进制的方式输出数据
    2. int main()
    3. {
    4. struct S tmp = { 0 };
    5. FILE* pf = fopen("test.txt", "rb");
    6. if (pf == NULL)
    7. {
    8. return 0;
    9. }
    10. //二进制的形式都文件
    11. //表示将pf中的数据写到tmp中
    12. fread(&tmp, sizeof(struct S), 1, pf);
    13. printf("%s %d %lf\n", tmp.name, tmp.age, tmp.score);
    14. fclose(pf);
    15. pf = NULL;
    16. return 0;
    17. }

    4. 文件的随机读写

    4 .1 fseek

    根据文件指针的位置和偏移量来定位文件指针

    int fseek ( FILE * stream, long int offset, int origin );

    1. int main()
    2. {
    3. FILE* pf = fopen("test.txt", "r");
    4. if (pf == NULL)
    5. {
    6. return 0;
    7. }
    8. //1.定位文件指针
    9. //fseek(要读取的文件,移动的字节数,起始位置)
    10. //SEEK_END:表示向前移动2个位置
    11. fseek(pf, -2, SEEK_END);
    12. //2.读取文件
    13. int ch = fgetc(pf);
    14. printf("%c\n", ch);
    15. fclose(pf);
    16. pf = NULL;
    17. return 0;
    18. }

    4.2 ftell

    返回文件指针相对于起始位置的偏移量

    long int ftell ( FILE * stream );
    1. //ftell:返回文件指针相对于起始位置的偏移量
    2. int main()
    3. {
    4. FILE* pf = fopen("test.txt", "r");
    5. if (pf == NULL)
    6. {
    7. return 0;
    8. }
    9. //2.读取文件
    10. int post = ftell(pf);
    11. printf("%d\n", post);//打开默认地址为0
    12. fclose(pf);
    13. pf = NULL;
    14. return 0;
    15. }
    1. int main()
    2. {
    3. FILE* pf = fopen("test.txt", "r");
    4. if (pf == NULL)
    5. {
    6. return 0;
    7. }
    8. //此时读取一个字符,则表示跳过第一个字符
    9. fgetc(pf);
    10. //2.读取文件
    11. int post = ftell(pf);
    12. printf("%d\n", post);//故此时输出为1
    13. fclose(pf);
    14. pf = NULL;
    15. return 0;
    16. }

    4.3 rewind

    让文件指针的位置回到文件的起始位置

    void rewind ( FILE * stream );
    
    1. //rewind:回到文件的起始位置
    2. int main()
    3. {
    4. FILE* pf = fopen("test.txt", "r");
    5. if (pf == NULL)
    6. {
    7. return 0;
    8. }
    9. int ch = fgetc(pf);
    10. printf("%c\n", ch);//读取出a
    11. rewind(pf);//返回原来的位置
    12. ch = fgetc(pf);
    13. printf("%c\n", ch);//读取出a
    14. fclose(pf);
    15. pf = NULL;
    16. return 0;
    17. }

    5. 文本文件和二进制文件

    6. 文件读取结束的判定

    6.1 被错误使用的feof

    feof:是用于判断文件读取结束的原因

    1. /*
    2. 文本文件读取结束:fgetc:pf==EOF
    3. fgets:pf=null
    4. 二进制文件读取结束:fread判断返回值是否小于实际要读的个数
    5. */
    6. int main()
    7. {
    8. //EOF
    9. //feof();//EOF - end of file - 文件结束标志
    10. FILE* pf = fopen("test.txt", "r");
    11. if (pf == NULL)
    12. return 0;
    13. int ch = fgetc(pf);
    14. printf("%d\n", ch);//-1
    15. fclose(pf);
    16. pf = NULL;
    17. return 0;
    18. }

    文本文件例子

    二进制文件例子:

    6.2 perror和strerror

    1. /*
    2. strerror:把错误码对应的错误信息的字符串地址返回
    3. peerror(s):参数 s 所指的字符串会先打印出,后面再加上错误原因字符串。
    4. */
    5. int main()
    6. {
    7. //strerror - 把错误码对应的错误信息的字符串地址返回
    8. //printf("%s\n", strerror(errno));
    9. //perror
    10. FILE* pf = fopen("test2.txt", "r");
    11. if (pf == NULL)
    12. {
    13. perror("open file test2.txt");//open file test2.txt:No such file or directory
    14. return 0;
    15. }
    16. //读文件
    17. fclose(pf);
    18. pf = NULL;
    19. return 0;
    20. }

    C语言 | perror函数使用详解_c语言线程perror_嵌入式大杂烩的博客-CSDN博客

    7.练习

     1. 求内存大小

    1. struct {
    2. int a;//0-3 4字节
    3. char b;//4 1字节
    4. short c;//6-7 2字节【因为是2字节,所以要使用2的倍数】
    5. short d;//8-9 2字节【因为是2字节,所以要使用2的倍数】
    6. };//10字节
    7. //所以我们应该直接+到12字节【地址为12-->(1,2,4)的最大倍数】

    2.sizeof(struct)

    1. struct A
    2. {
    3. int a;//0-3
    4. short b;//4-5
    5. //6-7
    6. int c;//8-11
    7. char d;//12
    8. //13 14 15
    9. };//13 -- > 16【(1,2,4)的最大倍数】
    10. struct B
    11. {
    12. int a;//0-3
    13. short b;//4-5
    14. char c;//6
    15. //7
    16. int d;//8-11
    17. };//12【(1,2,4)的最大倍数】
    18. int main()
    19. {
    20. printf("%d\n", sizeof(struct A));//16
    21. printf("%d\n", sizeof(struct B));//12
    22. return 0;
    23. }

    3.

    1. #pragma pack(4)/*编译选项,表示4字节对齐 平台:VS2013。语言:C语言*/
    2. int main(int argc, char* argv[])
    3. {
    4. struct tagTest1
    5. {
    6. short a;//0-1
    7. char d;//2
    8. 3
    9. long b;//4-7
    10. long c;//8-11
    11. };//12
    12. struct tagTest2
    13. {
    14. long b;//0-3
    15. short c;//4-5
    16. char d;//6
    17. 7
    18. long a;//8-11
    19. };//12
    20. struct tagTest3
    21. {
    22. short c;//0-1
    23. 2 3
    24. long b;//4-7
    25. char d;//8
    26. 9-11
    27. long a;//12-15
    28. };//16
    29. struct tagTest1 stT1;
    30. struct tagTest2 stT2;
    31. struct tagTest3 stT3;
    32. printf("%d %d %d", sizeof(stT1), sizeof(stT2), sizeof(stT3));
    33. return 0;
    34. }
    35. #pragma pack()

     

  • 相关阅读:
    Buran勒索病毒通过Microsoft Excel Web查询文件进行传播
    security实战
    探索银行的的IT架构
    java计算机毕业设计web企业档案管理系统MyBatis+系统+LW文档+源码+调试部署
    每条你收藏的资讯背后,都离不开TA
    售后处置跟踪系统设想
    阿里云ECS11月销量王 99元/年
    【学习笔记】ARC150/ARC151
    请问这个for loop的running time是多少?
    实战 | 电商业务性能测试(二): Jmeter 参数化功能实现注册登录的数据驱动
  • 原文地址:https://blog.csdn.net/m0_63077733/article/details/132911932