4.9对比一组函数:
scanf / fscanf / sscanfprintf / fprintf / sprintf
5. 文件的随机读写
5.1 fseek文件指针定位函数
介绍:根据文件指针的位置和偏移量来定位指针。
参数:offset 是偏移量。
参数:origin 是起始位置,有三种选项:
① SEEK_CUR 当前文件指针的位置开始偏移。
② SEEK_END 文件的末尾位置开始偏移。
③ SEEK_SET 文件的起始位置开始偏移。
代码演示:手动创建一个文件,打开文件随便写点内容
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读取文件 int ch = fgetc(pf); printf("%c\n", ch);//a ch = fgetc(pf); printf("%c\n", ch);//b ch = fgetc(pf); printf("%c\n", ch);//c // 关闭文件 fclose(pf); pf = NULL; return 0; }
如果我想得到 a a b,该怎么做?可以试着使用 fseek 函数:
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读取文件 int ch = fgetc(pf); printf("%c\n", ch);//a // 调整文件指针 fseek(pf, -1, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为-1,向前移动1个单位 ch = fgetc(pf); printf("%c\n", ch);//a ch = fgetc(pf); printf("%c\n", ch);//b // 关闭文件 fclose(pf); pf = NULL; return 0; }
用 SEEK_SET ,打印 a d e:
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读取文件 int ch = fgetc(pf); printf("%c\n", ch);//a // 调整文件指针 fseek(pf, 3, SEEK_SET); // SEEK_SET为文件的起始位置,偏移量为3,向后移动3个单位 ch = fgetc(pf); printf("%c\n", ch);//d ch = fgetc(pf); printf("%c\n", ch);//e // 关闭文件 fclose(pf); pf = NULL; return 0; }
用 SEEK_END ,打印 a e f :
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 读取文件 int ch = fgetc(pf); printf("%c\n", ch);//a // 调整文件指针 fseek(pf, -2, SEEK_END); // SEEK_END为当前文件末尾位置,偏移量为-2,向前移动2个单位 ch = fgetc(pf); //如果写test6.txt时加了回车就会出错 printf("%c\n", ch);//e ch = fgetc(pf); printf("%c\n", ch);//f // 关闭文件 fclose(pf); pf = NULL; return 0; }
5.2 ftell返回偏移量函数
在上边创建好test.txt后,代码演示:ftell 的使用方法
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 调整文件指针 fseek(pf, 5, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为5,向后移动5个单位 // 读取文件 int ch = fgetc(pf); printf("%c\n", ch); // f // 返回偏移量 int ret = ftell(pf); printf("%d\n", ret); // 6 // 关闭文件 fclose(pf); pf = NULL; return 0; }
5.3 rewind 文件指针回到起始位置函数
介绍:rewind(意为倒带(我受够了等待~你所谓的安排~),磁带倒带),
设置文件位置为给定流 stream 的文件的开头,
让文件指针回到起始位置。
代码演示:利用 rewind 函数让文件指针回到起始位置
#include <stdio.h> int main() { FILE* pf = fopen("test6.txt", "r"); if (pf == NULL) { perror("fopen"); return 1; } // 调整文件指针 fseek(pf, 5, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为5,向后移动5个单位 // 读取文件 int ch = fgetc(pf); printf("%c\n", ch); // f // 返回偏移量 int ret = ftell(pf); printf("%d\n", ret); // 6 // 让文件指针回到起始位置 rewind(pf); ch = fgetc(pf); //再读取一次 printf("%c\n", ch);//a // 关闭文件 fclose(pf); pf = NULL; return 0; }
6. 文本文件和二进制文件
再上一节中,我们已经对文本文件和二进制文件开了个头,在这里将进行详细探讨。
根据数据的组织形式,数据文件被称为文本文件或者二进制文件。
6.1 文本文件
什么是文本文件?
如果要求在外存上以 ASCII 码的形式存储,则需要在存储之前进行转换。
以 ASCII 字符的形式存储的文件,就是文本文件。
6.2 二进制文件
什么是二进制文件?
数据在内存中以二进制的形式存储,如果不加以转换地输出到外存,就是二进制文件。
6.3 数据在文件中的存储方式
一个数据在文件中是如何存储的呢?
存储方式如下:
① 字符一律以 ASCII 形式存储。
② 数值型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储。
举个简单的例子:比如整数10000,如果以 ASCII 码的形式形式输出到磁盘,
则磁盘中占用5个字节(每个字符占1个字节)。而如果以二进制的形式输出,
则在磁盘上只占4个字节。
测试代码:
#include <stdio.h> int main() { int a = 10000; FILE* pf = fopen("test6.txt", "wb"); if (pf == NULL) { perror("fopen"); return 1; } // 写文件 fwrite(&a, sizeof(int), 1, pf); // 二进制的形式写到文件中 // 关闭文件 fclose(pf); pf = NULL; return 0; }
(代码成功运行后打卡文件就发现是乱码)
使用强大的VS来打开我们的二进制文件 test6.txt ,
详细步骤如下:
点击源文件添加现有项,选中刚才的二进制文件(test6.txt)
添加到VS后选择打开方式,向下拉,选择二进制编辑器打开:
最后,我们来检测一下 10000 是不是 10 27 00 00 :
10000的二进制:0000 0000 0000 0000 0010 0111 0001 0000
转化为十六进制(八位转两位):00 00 27 10
小端倒过来就是10 27 00 00
总结:文本文件和二进制文件的存储方式
① 文本文件:将内存里的数据转换成 ASCII 码值的形式存储到文件中。
② 二进制文件:将内存里的二进制数据不加任何转化直接存储到二进制文件中。
C语言进阶⑲(文件下篇)(文件读写+文本文件和二进制文件+EOF+文件缓冲区)(下):https://developer.aliyun.com/article/1513250