p59 随机读写文件
需要移动文件内部的位置指针,再来进行读写。允许从文件的任意位置开始读写
位置指针,方便对文件的读写进行控制。系统为每个打开的文件设置了一个位置指示器,主要用于表示当前的读写位置。使用 ftell 函数获取位置指示器的值。
# include <stdio.h>
# include <stdlib.h>
int main(void){
/* ftell 函数的返回值是一个long类型的值,因为文件可能会很长,
用long类型的值存储当前的读写位置,从某种意义上来说,文件里面的位置
是以数组的形式来存放,每一个位置有一个下标,ftell返回下标值*/
FILE *fp;
if((fp = fopen("hello.txt","w"))== NULL){
printf("文件打开失败!\n");
exit(EXIT_FAILURE);
}
printf("%ld\n",ftell(fp));
// 打印当前的位置指示器的值
fputc('F',fp);
printf("%ld\n",ftell(fp));
fputs("ishC\n",fp);
printf("%ld\n",ftell(fp));
rewind(fp);
fputs("Hello",fp);
// 此时插入数据会直接覆盖里面有的部分
fclose(fp);
return 0;
}
如何修改位置指示器的值? rewind函数,将位置指示器移动到文件头的位置。
随机读写:使用fseek函数
fseek函数用于设置文件流的位置指示器
# include <stdio.h>
int fseek(FILE *stream, long int offset, int whence);
offset: 指定从whence 参数的位置起偏移多少个字节
whence: 指定从开始偏移的位置,该参数可以使用下面任一值:
SEEK_SET 文件头, SEEK_CUR 当前的读写位置 , SEEK_END 文件末尾
调用成功: 返回值 0
# include <stdio.h>
# include <stdlib.h>
# define N 4
struct Stu{
char name[24];
int num;
float score;
}stu[N], sb;
int main(void){
FILE *fp;
int i;
if( (fp = fopen("sorce.txt","wb")) == NULL){
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
printf("请开始录入成绩 (格式: 姓名 学号 成绩)\n");
for(i = 0; i < N;i++){
scanf("%s %d %f",stu[i].name,&stu[i].num,&stu[i].score);
}
fwrite(stu,sizeof(struct Stu),N,fp);
// 结构体用二进制写入函数
fclose(fp);
if( (fp = fopen("sorce.txt","rb")) == NULL){
printf("打开文件失败!\n");
exit(EXIT_FAILURE);
}
fseek(fp,sizeof(struct Stu),SEEK_SET);
// 打印第二个,所以偏移一个结构体的位置
fread(&sb,sizeof(struct Stu),1,fp);
printf("%s(%d) 的成绩是: %.2f\n",sb.name,sb.number,sb.score);
fclose(fp);
return 0;
// vi score.txt
}
不同操作系统对字符的存放不是完全一致的:
- 对于以二进制模式打开的文件,fseek函数在某些操作系统可能不支持SEEK_END位置。
- 对于以文本模式打开的文件,fseek函数的whence参数只能取 SEEK_SET 才是有意义的,并且传递给offset参数的值要么是0,要么是上一层对同个文件调用ftell函数获得的返回值。