当前位置:   article > 正文

C语言文件操作_fwrite实例

fwrite实例

在程序设计中文件有两种,一种是程序文件(包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe))另外一种就是数据文件(文件的文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件, 或者输出内容的文件),也就是本篇文章所介绍的东东啦。

目录

文件名

文件类型

文件的打开和关闭

1.文件指针

2.fopen

3.fclose

文件的顺序读写

1.fputc

2.fgetc

3.fputs

4.fgets

5.fprintf

6.fscanf

7.fwrite

8.fread

对比printf,fprintf,,sprintf 

文件的随机读写 

1.fseek

2.ftell

3.rewind

文件读写结束的判断


文件名

一个文件要有一个唯一的文件标识,以便用户识别和引用,而我们通常称文件标识为文件名。文件名包含3 部分: 文件路径 + 文件名主干 + 文件后缀 例如: (c:\code\test.txt)
注意文件名不能包含一些特殊字符: \   /  :  *  ?  "  <  >  |

文件类型

数据文件根据数据的组织形式还可以分为文本文件和二进制文件。

二进制文件:数据在内存中以二进制的形式存储,如果不加转换的输出到外存就是二进制文件

文本文件:如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件

流是个抽象的概念,是对输入输出设备(文件,网络,内存等)的抽象,对于数据的输入/输出操作都是以“流”的方式进行。当程序需要从某个数据源读入数据的时候,就会开启一个输入流,数据源可以是文件、内存或网络等等。相反地,需要写出数据到某个数据源目的地的时候,也会开启一个输出流,这个数据源目的地也可以是文件、内存或网络等等。

任何一个C程序,只有运行起来就会默认打开3个流:FILE* stdin(标准输入流:对应键盘)

FILE* stdout(标准输出流:对应屏幕)FILE* stderr(标准错误流:应屏幕)

文件的打开和关闭

在对文件进行读写操作前后分别需要对文件进行打开和关闭的操作。其操作离不开文件指针。

1.文件指针

文件指针(如:FILE* pf)是用来维护文件的。每个文件被使用的时候都会在内存中开辟了一个相应的文件信息区,文件信息区存放有文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息会被保存在一个名为FILE的结构体变量中,通过一个FILRE的指针可以维护该结构体,进而访问对应的文件。

2.fopen

fopen函数是用来打开文件的函数,

它的返回值FILE*,即打开文件的同时返回一个FILE*的指针变量指向该文件,也相当于建立了文件和指针的关系第一个参数(const char* filename)为字符串,包含要打开的文件的名称第二个参数(const char* mode)为模式说明符(文件的打开方式),代表文件的读写权限。

第二个参数文件打开方式最基本的有以下几种方式:

控制读写权限的字符串(必须指明)
打开方式说明
"r"r(read),以“只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。
"w"w(write),以“写入”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
"a"a(append),以“追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
"r+"以“读写”方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。
"w+"以“写入/更新”方式打开文件,相当于wr+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
"a+"以“追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
控制读写方式的字符串(可以不写)
打开方式说明
"t"t(text),文本文件。如果不写,默认为"t"
"b"b(binary),二进制文件。
调用 fopen() 函数时必须指明读写权限,但是可以不指明读写方式(此时默认为"t")。

读写权限和读写方式可以组合使用,但是必须将读写方式放在读写权限的中间或者尾部(换句话说,不能将读写方式放在读写权限的开头)。例如:

1.将读写方式放在读写权限的末尾:"rb"、"wt"、"ab"、"r+b"、"w+t"、"a+t"

2.将读写方式放在读写权限的中间:"rb+"、"wt+"、"ab+“

注:使用fopen函数需要判断文件是否打开成功,若打开失败则返回空指针

3.fclose

fclose函数是用来关闭文件的,

它的返回值为int,如果成功关闭,则返回零值,关闭失败,返回 EOF。返回参数(FILE* stream)为要关闭的文件的 FILE 对象的指针。注意关闭文件后最好将文件指针置空。

下面是文件的打开和关闭的操作样例

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE* pf = fopen("test.txt","w");//打开文件
  5. if (pf == NULL)//判断打开成功与否
  6. {
  7. perror("FILE:");
  8. return 1;
  9. }
  10. //进行读写操作
  11. //...
  12. //结束读写操作
  13. fclose(pf);//关闭文件
  14. pf = NULL;
  15. return 0;
  16. }

文件的顺序读写

1.fputc

fputc函数在文件的读写中用于把一个字符写入指定的文件中,

返回类型为int,写入成功则返回写入的字符,写入错误则返回 EOF 第一个参数(int character)为要写入的字符(写入时,该值在内部转换为无符号字符)。第二个参数(FILE* stream)为指向要访问的文件的文件指针。

下面是fgetc函数的使用样例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE* pf = fopen("test.txt", "w");//以写方式打开文件
  5. if (pf == NULL)//判断打开成功与否
  6. {
  7. perror("FILE:");
  8. return 1;
  9. }
  10. fputc("a", pf)//将字符a写入pf所指向的文件中
  11. fclose(pf);//关闭文件
  12. pf = NULL;
  13. return 0;
  14. }

2.fgetc

fgetc函数在文件的读写中用于从指定的文件中读一个字符

返回类型为int,成功后返回读取的字符(提升为 int 值),失败返回EOF函数参数(FILE* stream)为指向要访问的文件的文件指针。

下面是fgetc函数的使用样例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE* pf = fopen("test.txt", "r");//以读方式打开文件
  5. if (pf == NULL)//判断打开成功与否
  6. {
  7. perror("FILE:");
  8. return 1;
  9. }
  10. while(ch=fgetc(pf)!=EOF)//读取pf所值向的文件内容
  11. {
  12. printf("%c",ch);//打印读到的内容
  13. }
  14. fclose(pf);//关闭文件
  15. pf = NULL;
  16. return 0;
  17. }

3.fputs

fputs函数在文件的读写中用于向指定的文件写入一个字符串

返回类型为int,写入成功则返回非负值写入错误则返回 EOF 第一个参数(const char* str)为要写入的字符串的起始地址。第二个参数(FILE* stream)为指向要访问的文件的文件指针。

下面是fputs函数的使用

样例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE* pf = fopen("test.txt", "w");//以写方式打开文件
  5. if (pf == NULL)//判断打开成功与否
  6. {
  7. perror("FILE:");
  8. return 1;
  9. }
  10. fputs("abc",pf);//将字符串abc写入pf所指向的文件中
  11. fclose(pf);//关闭文件
  12. pf = NULL;
  13. return 0;
  14. }

4.fgets

fgets函数在文件的读写中用于从文件中读取字符并将其作为 C 字符串存储到 str 中,直到读取 (num-1) 字符或达到换行符或文件末尾(以先发生者为准)(注:1.换行符会使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中 。   2.终止空字符也会自动追加到复制到 str 的字符之后。)
 返回类型为char*,读取成功返回指向在其中复制字符串读取的数组的指针,读取失败返回空指针第一个参数(char* str)为指向在其中复制字符串读取的数组的指针第二个参数(int num)为要复制到 str 中的最大字符数(包括终止空字符)第三个参数(FILE* stream)为指向要访问的文件的文件指针

下面是fgets函数的使用样例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. FILE* pf = fopen("test.txt", "r");//以读方式打开文件
  5. if (pf == NULL)//判断打开成功与否
  6. {
  7. perror("FILE:");
  8. return 1;
  9. }
  10. char arr[10] = { 0 };
  11. fgets(arr,5,pf); //进行读操作
  12. printf("%s\n", arr);
  13. fclose(pf);//关闭文件
  14. pf = NULL;
  15. return 0;
  16. }

5.fprintf

fprintf在文件的读写中用于将格式化的数据写入文件

fprint的用法可以类比printf的用法

对比一下可以发现fprintf比printf就多加了一个参数 (FILE* stream),这样我们很容易可以得到下面fprintf的使用样例:

  1. #include<stdio.h>
  2. struct a
  3. {
  4. int m;
  5. char p;
  6. }a1={2,‘a’};
  7. int main()
  8. {
  9. FILE* pf = fopen("test.txt", "w");
  10. if (pf == NULL)
  11. {
  12. perror("FILE:");
  13. return 1;
  14. }
  15. fprintf(pf, "%d", a1.m);//比printf多一个参数pf
  16. fclose(pf);
  17. pf = NULL;
  18. return 0;
  19. }

结合流的内容,printf("%d",a);也可以写成fprintf(stdout,"%d",a);

6.fscanf

fscanf在文件的读写中用于从文件中读取数据,并根据参数格式将其存储到附加参数所指向的位置

 fscanf的用法也可以类比scanf的用法

 对比一下同样发现fscanf比scanf就多加了一个参数 (FILE* stream),这样我们很容易可以得到下面fprintf的使用样例:

  1. #include<stdio.h>
  2. struct a
  3. {
  4. int m;
  5. char p;
  6. }a1;
  7. int main()
  8. {
  9. FILE* pf = fopen("test.txt", "r");
  10. if (pf == NULL)
  11. {
  12. perror("FILE:");
  13. return 1;
  14. }
  15. fscanf(pf, "%d", &a1.m);//比scanf多一个参数pf
  16. printf("%d\n",a1.m);
  17. fclose(pf);
  18. pf = NULL;
  19. return 0;
  20. }

7.fwrite

fwritez函数在文件的读写中用于将数据块以二进制的形式写到文件中

 返回值为成功写入的元素总数,如果该数字与 count 参数不同,则会出现写入错误第一个参数(const void* ptr)为指向要写入的元素数组的指针第二个参数(size_t size)为要写入的每个元素的大小(以字节为单位)第三个参数(size_t count)为要写入的元素数,每个元素的大小为size字节第四个参数(FILE* stream)为指向要访问的文件的文件指针。

下面是fwrite函数的使用样例:

  1. #include<stdio.h>
  2. struct S
  3. {
  4. char arr[10];
  5. int a;
  6. };
  7. int main()
  8. {
  9. struct S s = { "abc",21 };
  10. FILE* pf = fopen("text.txt", "wb");
  11. if (pf == NULL)
  12. {
  13. perror("FILE:");
  14. return 1;
  15. }
  16. fwrite(&s, sizeof(struct S), 1, pf);
  17. fclose(pf);
  18. pf = NULL;
  19. return 0;
  20. }

8.fread

fread函数在文件的读写中用于以二进制的形式读取数据。

返回值为成功读取的元素总数,如果该数字与 count 参数不同,或者读到文件末尾,则会出现写入错误第一个参数(void* ptr)为值向大小至少为(大小*计数)字节的内存块的指针,转换为void*第二个参数(size_t size)为要读取的每个元素的大小(以字节为单位)第三个参数(size_t count)为要读取的元素数,每个元素的大小为size字节第四个参数(FILE* stream)为指向要访问的文件的文件指针。

下面是fwrite函数的使用样例:

  1. #include<stdio.h>
  2. struct S
  3. {
  4. char arr[10];
  5. int a;
  6. };
  7. int main()
  8. {
  9. struct S s = { "abc",21 };
  10. FILE* pf = fopen("text.txt", "wb");
  11. if (pf == NULL)
  12. {
  13. perror("FILE:");
  14. return 1;
  15. }
  16. fread(&s, sizeof(struct S), 1, pf);
  17. printf("%s %d\n", s.arr, s.a);
  18. fclose(pf);
  19. pf = NULL;
  20. return 0;
  21. }

对比printf,fprintf,,sprintf 

​​​​​​printf,scanf和fscanf,fprintf我们都见识过了,那么这里就再介绍两个函数:sprintf和sscanf

sprintf

sprintf函数用于把一个格式化的数据写到字符串中,

用法和fprintf差不多,只是把文件指针换成字符指针,废话就不多说了,直接上样例:

  1. #include<stdio.h>
  2. int main()
  3. {
  4. struct S s = { "abc",3 };
  5. char buf[100];
  6. sprintf(buf,"%s %d", s.arr, s.n);
  7. printf("%s", buf);//打印结果为abc 3
  8. return 0;
  9. }

sscanf
sscanf函数是用于从一个字符串中转化出一个格式化的数据,

 看样用法样例:

  1. struct S
  2. {
  3. char arr[10];
  4. int n;
  5. };
  6. #include<stdio.h>
  7. int main()
  8. {
  9. struct S s = { 0 };
  10. char buf[10] = "abc 3";
  11. sscanf(buf, "%s %d", s.arr, &s.n);
  12. printf("%s %d", s.arr, s.n);//打印结果为abc 3
  13. return 0;
  14. }

总结

scanf:是针对标准输入的格式化输入语句

printf:是针对标准输出的格式化输出语句

fscanf:是针对所有输入流的格式化输入语句

fprintf:是针对所有输出流的格式化输出语句

sscanf:是从一个字符串中转化出一个格式化的数据

sprintf:是把一个格式化的数据转化成字符串

文件的随机读写 

1.fseek

fseek函数用于根据文件指针的位置和偏移量来定位文件指针。

返回类型为int,成功返回零,否则返回非零值第一个参数(FILE* stream)为指向要访问的文件的文件指针第二个参数(long int offset)若为二进制文件则是要从偏移的字节数,若为文本文件则是零或 ftell 返回的值第三个参数(int origin)用作偏移参考的位置,它由常量(SEEK_SET(文件开头),SEEK_CUR(文件指针的当前位置),SEEK_END(文件结尾))之一指定,这些常量在 <stdio.h>专门用作此函数的参数

 

2.ftell

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

返回类型为long int,成功则返回仓位指标的当前值,失败返回 -1L 。参数FILE* stream)为指向要访问的文件的文件指针

3.rewind

rewind函数用于让文件指针的位置回到文件的起始位置。

就喜欢这种参数返回类型简单明了的函数,哈哈

再看看随机读写用法样例子:

  1. #include<stdio.h>
  2. struct S
  3. {
  4. char arr[10];
  5. int m;
  6. }s1[10], s2;
  7. int main()
  8. {
  9. struct S s1[10] = { {"abc",1},{"def",2},{"gew",3} };
  10. FILE* pf = fopen("text.txt", "wb+");
  11. if (pf == NULL)
  12. {
  13. perror("FILE");
  14. return 1;
  15. }
  16. fwrite(s1, sizeof(struct S), 3, pf);//写入3条信息
  17. fseek(pf, sizeof(struct S), SEEK_SET);//移动文件指针
  18. fread(&s2, sizeof(struct S), 1, pf);//读取一条信息
  19. printf("%s %d", s2.arr, s2.m);//打印结果为:def 2
  20. fclose(pf);
  21. pf = NULL;
  22. return 0;
  23. }

文件读写结束的判断

1. 文本文件读取是否结束,判断返回值是否为 EOF fgetc ),或者 NULL fgets
例如:
fgetc 判断是否为 EOF .
fgets 判断返回值是否为 NULL .
  1. int main()
  2. {
  3. FILE* pf = fopen("text.txt", "r");
  4. if (pf == NULL)
  5. {
  6. perror("FILE:");
  7. return 1;
  8. }
  9. char ch = 0;
  10. while ((ch = fgetc(pf)) != EOF)/*fgetc 当读取失败的时候或者遇到文件结束的时候,都会返回EOF*/
  11. {
  12. putchar(ch);
  13. }
  14. //判断是什么原因结束的
  15. if (ferror(pf))
  16. {
  17. puts("I/O error when reading");
  18. }
  19. else if(feof(pf))
  20. {
  21. puts("End of file reached successfully");
  22. }
  23. fclose(pf);
  24. pf = NULL;
  25. return 0;
  26. }

2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
fread 判断返回值是否小于实际要读的个数。
  1. #include <stdio.h>
  2. enum { SIZE = 5 };
  3. int main(void) {
  4. double a[SIZE] = { 1.,2.,3.,4.,5. };
  5. FILE* fp = fopen("test.bin", "wb"); // 必须用二进制模式
  6. fwrite(a, sizeof * a, SIZE, fp); // 写 double 的数组
  7. fclose(fp);
  8. double b[SIZE];
  9. fp = fopen("test.bin", "rb");
  10. size_t ret_code = fread(b, sizeof * b, SIZE, fp); // 读 double 的数组
  11. if (ret_code == SIZE) {
  12. puts("Array read successfully, contents: ");
  13. for (int n = 0; n < SIZE; ++n) printf("%f ", b[n]);
  14. putchar('\n');
  15. }
  16. else { // error handling
  17. if (feof(fp))
  18. printf("Error reading test.bin: unexpected end of file\n");
  19. else if (ferror(fp)) {
  20. perror("Error reading test.bin");
  21. }
  22. }
  23. fclose(fp);
  24. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/384368
推荐阅读
相关标签
  

闽ICP备14008679号