当前位置: 首页 > article >正文

C语言:以数据块的形式读写文件

1、以数据块形式读写文件

fgets() 有局限性,每次最多只能从文件中读取一行内容,因为 fgets() 遇到换行符就结束读取。如果希望读取多行内容,需要使用 fread() 函数;相应地写入函数为 fwrite()。

fread() 函数用来从指定文件中读取块数据。所谓块数据,也就是若干个字节的数据,可以是一个字符,可以是一个字符串,可以是多行数据,并没有什么限制。fread() 的原型为:

fwrite() 函数用来向文件中写入块数据,它的原型为:

size_t fwrite ( void * ptr, size_t size, size_t count, FILE *fp );

对参数的说明:

 ptr 为内存区块的指针,它可以是数组、变量、结构体等。fread() 中的 ptr 用来存放读取到的数据,fwrite() 中 的 ptr 用来存放要写入的数据。  size:表示每个数据块的字节数。  count:表示要读写的数据块的块数。  fp:表示文件指针。  理论上,每次读写 size*count 个字节的数据。

size_t 是在 stdio.h 和 stdlib.h 头文件中使用 typedef 定义的数据类型,表示无符号整数,也即非负数,常用来表示数量。

返回值:返回成功读写的块数,也即 count。如果返回值小于 count:

 对于 fwrite() 来说,肯定发生了写入错误,可以用 ferror() 函数检测。  对于 fread() 来说,可能读到了文件末尾,可能发生了错误,可以用 ferror() 或 feof() 检测。

【示例】从键盘输入一个数组,将数组写入文件再读取出来。

1. #include<stdio.h>
2. #define N 5
3. int main(){
4. //从键盘输入的数据放入a,从文件读取的数据放入b
5. int a[N], b[N];
6. int i, size = sizeof(int);
7. FILE *fp;
8.
9. if( (fp=fopen("D:\\\\demo.txt", "rb+")) == NULL ){ //以二进制方式打开
10. puts("Fail to open file!");
11. exit(0);
12. }
13. 
14. //从键盘输入数据 并保存到数组a
15. for(i=0; i<N; i++){
16. scanf("%d", &a[i]);
17. }
18. //将数组a的内容写入到文件
19. fwrite(a, size, N, fp);
20. //将文件中的位置指针重新定位到文件开头
21. rewind(fp);
22. //从文件读取内容并保存到数组b
23. fread(b, size, N, fp);
24. //在屏幕上显示数组b的内容
25. for(i=0; i<N; i++){
26. printf("%d ", b[i]);
27. }
28. printf("\\n");
29.
30. fclose(fp);
31. return 0;
32. }

运行结果: 23 409 500 100 222↙ 23 409 500 100 222

打开 D:\\demo.txt,发现文件内容根本无法阅读。这是因为我们使用"rb+"方式打开文件,数组会原封不动地以二进制形式写入文件,一般无法阅读。

数据写入完毕后,位置指针在文件的末尾,要想读取数据,必须将文件指针移动到文件开头,这就是 rewind(fp);的作用。

文件的后缀不一定是 .txt,它可以是任意的,你可以自己命名,例如 demo.ddd、demo.doc、demo.diy 等。

【示例】从键盘输入两个学生数据,写入一个文件中,再读出这两个学生的数据显示在屏幕上。

1. #include<stdio.h>
2.
3. #define N 2
4.
5. struct stu{
6. char name[10]; //姓名
7. int num; //学号
8. int age; //年龄
9. float score; //成绩
10. }boya[N], boyb[N], *pa, *pb;
11.
12. int main(){
13. FILE *fp;
14. int i;
15. pa = boya;
16. pb = boyb;
17. if( (fp=fopen("d:\\\\demo.txt", "wb+")) == NULL ){
18. puts("Fail to open file!");
19. exit(0);
20. }
21.
22. //从键盘输入数据
23. printf("Input data:\\n");
24. for(i=0; i<N; i++,pa++){
25. scanf("%s %d %d %f",pa->name, &pa->num,&pa->age, &pa->score);
26. }
27. //将数组 boya 的数据写入文件
28. fwrite(boya, sizeof(struct stu), N, fp);
29. //将文件指针重置到文件开头
30. rewind(fp);
31. //从文件读取数据并保存到数据 boyb
32. fread(boyb, sizeof(struct stu), N, fp);
33.
34. //输出数组 boyb 中的数据
35. for(i=0; i<N; i++,pb++){
36. printf("%s %d %d %f\\n", pb->name, pb->num, pb->age, pb->score);
37. }
38. fclose(fp);
39. return 0;
40. }

运行结果: Input data:

Tom 2 15 90.5↙

Hua 1 14 99↙

Tom 2 15 90.500000

Hua 1 14 99.000000

2、格式化读写文件

fscanf() 和 fprintf() 函数与前面使用的 scanf() 和 printf() 功能相似,都是格式化读写函数,两者的区别在于 fscanf()和 fprintf() 的读写对象不是键盘和显示器,而是磁盘文件。

这两个函数的原型为:

int fscanf ( FILE *fp, char * format, ... );
int fprintf ( FILE *fp, char * format, ... );

fp 为文件指针,format 为格式控制字符串,... 表示参数列表。与 scanf() 和 printf() 相比,它们仅仅多了一个 fp参数。例如:

1. FILE *fp;
2. int i, j;
3. char *str, ch;
4. fscanf(fp, "%d %s", &i, str);
5. fprintf(fp,"%d %c", j, ch);

fprintf() 返回成功写入的字符的个数,失败则返回负数。fscanf() 返回参数列表中被成功赋值的参数个数。

【示例】用 fscanf 和 fprintf 函数来完成对学生信息的读写。

1. #include<stdio.h>
2.
3. #define N 2
4.
5. struct stu{
6. char name[10];
7. int num;
8. int age;
9. float score;
10. } boya[N], boyb[N], *pa, *pb;
11.
12. int main(){
13. FILE *fp;
14. int i;
15. pa=boya;
16. pb=boyb;
17. if( (fp=fopen("D:\\\\demo.txt","wt+")) == NULL ){
18. puts("Fail to open file!");
19. exit(0);
20. }
21.
22. //从键盘读入数据,保存到boya
23. printf("Input data:\\n");
24. for(i=0; i<N; i++,pa++){
25. scanf("%s %d %d %f", pa->name, &pa->num, &pa->age, &pa->score); 
26. }
27. pa = boya;
28. //将boya中的数据写入到文件
29. for(i=0; i<N; i++,pa++){
30. fprintf(fp,"%s %d %d %f\\n", pa->name, pa->num, pa->age, pa->score); 
31. }
32. //重置文件指针
33. rewind(fp);
34. //从文件中读取数据,保存到boyb
35. for(i=0; i<N; i++,pb++){
36. fscanf(fp, "%s %d %d %f\\n", pb->name, &pb->num, &pb->age, &pb->score);
37. }
38. pb=boyb;
39. //将boyb中的数据输出到显示器
40. for(i=0; i<N; i++,pb++){
41. printf("%s %d %d %f\\n", pb->name, pb->num, pb->age, pb->score);
42. }
43.
44. fclose(fp);
45. return 0;
46. }

运行结果:

Input data:
Tom 2 15 90.5↙
Hua 1 14 99↙
Tom 2 15 90.500000
Hua 1 14 99.000000

打开 D:\\demo.txt,发现文件的内容是可以阅读的,格式非常清晰。用 fprintf() 和 fscanf() 函数读写配置文件、日志文件会非常方便,不但程序能够识别,用户也可以看懂,可以手动修改。

如果将 fp 设置为 stdin,那么 fscanf() 函数将会从键盘读取数据,与 scanf 的作用相同;设置为 stdout,那么fprintf() 函数将会向显示器输出内容,与 printf 的作用相同。例如:

1. #include<stdio.h>
2. int main(){
3. int a, b, sum;
4. fprintf(stdout, "Input two numbers: ");
5. fscanf(stdin, "%d %d", &a, &b);
6. sum = a + b;
7. fprintf(stdout, "sum=%d\\n", sum);
8. return 0;
9. }

运行结果:

Input two numbers: 10 20↙

sum=30

 


http://www.kler.cn/a/445905.html

相关文章:

  • Docker 清理命令
  • 使用C#调用SAP的WebService接口
  • 【工作记录】springboot应用中使用Jasypt 加密配置文件@20241216
  • 微信小程序:轻应用的未来与无限可能
  • Fortify 24.2.0版本最新版 win/mac/linux
  • 网络和IP地址计算器方案
  • JVM 详解
  • 大数据-252 离线数仓 - Airflow 任务调度 Crontab简介 任务集成部署 入门案例
  • 中间件 redis安装
  • 洛谷 B3644 【模板】拓扑排序 / 家谱树 C语言
  • git部分命令的使用
  • Hmsc包开展群落数据联合物种分布模型分析通用流程(Pipelines)
  • 如何快速构建Jmeter脚本
  • oracle AES CBC,128位密钥加解密方法
  • 【C++ DFS 图论】1519. 子树中标签相同的节点数|1808
  • 解决 Ubuntu 20.04 上因 postmaster.pid 文件残留导致的 PostgreSQL 启动失败问题
  • L24.【LeetCode笔记】 杨辉三角
  • 如何彻底删除电脑数据以防止隐私泄露
  • 【mac 终端美化】oh my zsh
  • GTID详解