引入

我们之前讲的,都是对文件的顺序读写,很容易操作,但有时候效率不高。比如,文件中有1000个数据,我们如果需要找到第999号数据,那么需要从1遍历到998才可以。如果是一个城市几百万人的数据呢?所以随机访问应运而生,随机访问不是按数据在文件中的物理位置进行读写,而是可以对任何位置上的数据进行访问,显然这种方法比顺序访问高效的多。

文件位置标记

我们前面说过,w 方式打开是新建(有重名就删除再新建),文件标记在开头。a 方式打开是追加,文件标记在末尾。为了对读写进行控制,系统位每个文件设置了一个文件读写位置标记,简称(文件读写标记或文件标记),用来指示接下来要读写的下一个字符的位置

文件位置读写标记

  • **顺序读文件:**一般情况下,在对字符文件进行顺序读写的时候,文件位置标记指向文件开头,这时,如果对文件进行读的操作,然后文件位置标记向后移动一个位置,如果再一次执行读操作,就会将位置2的字符读入,以此类推(我们前面的例子也说过)直到文件尾。
  • **顺序写文件:**一般情况下,在对字符文件进行顺序写的时候,文件位置标记指向文件开头,这时,如果对文件进行写的操作,每写完一个文件位置标记顺序后移一个位置。然后在下一次执行写操作的时候,把数据写入指针所在位置。直到把全部数据写完,此时文件位置标记在最后一个数据之后(因为写完就向后移动了嘛)。
  • **随机读写:**如果我们人为的移动文件标记位置,文件标记位置可以向前、向后、向文件头、向文件尾移动,然后对该位置进行读写,这就不是顺序读写了,而是随机读写

流文件,我们可以进行顺序读写也可以进行随机读写,关键在于文件读写标记位置的控制方式。如果是按字节顺序移动的,就是顺序读写,如果能将文件位置标记按需要移动到任意位置的,那就是随机读写了!

文件位置标记的定位

我们清楚了文件位置标记,也知道了怎样操作文件位置标记是随机读写,怎样操作是顺序读写。现在我们就来看看,如果操作文件标记。

rewind 函数

作用:将文件位置标记重新返回文件的开头,无返回值。

例子

将磁盘中的文件,先输出一次,再复制一份。

#include <stdio.h>
#include <stdlib.h>
int main(){
    FILE *fp,*cfp;
    fp=fopen("/Users/liulin/1.txt","r");
    cfp=fopen("/Users/liulin/2.txt","w");
    //第一遍
    while(!feof(fp)){
        putchar(fgetc(fp));
    }
    printf("\n显示成功第一遍\n");
    //第二遍
    while(!feof(fp)){
        putchar (getc(fp));
    }
    printf("\n第二遍不显示\n");
    //第三遍,回到文件头
    rewind(fp);
    while(!feof(fp)){
        putchar (getc(fp));
    }
    printf("\n第三遍文件位回到文件头,正常显示了!\n");
    //复制文件,回到文件头
    rewind(fp);
    while(!feof(fp)){
        fputc(getc(fp),cfp);
    }
    fclose(fp);
    fclose(cfp);
    return 0;
}

无论是输出也好,复制也好,我们之前都讲过,非常简单。但是这两个操作如果连着来,就不简单了,因为要涉及到文件标记位置的问题。第一遍,输出文件的时候,已经到了文件尾,所以我用同样的方式输出第二遍的时候,是没有内容的。第三遍的时候,我是用rewind(fp)将 fp 的文件位置返回到文件头,此时再看,又能输出了,然后再回到文件头,进行复制文件。

fseek 函数

作用:用于改变文件位置标记。
一般形式是

fseek(文件类型指针,位移量,起始点)

  • **文件类型指针:**我们就不说了
  • **起始点:**用0、1、2表示,0 代表文件开始位置,1 代表当前位置,2 代表文件末尾位置
起始点 名字 数字代表
文件开始位置 SEEK_SET 0
文件当前位置 SEEK_CUR 1
文件末尾位置 SEEK_END 2
  • **位移量:**以起始点为基点,向前移动的字节数,位移量应该是 long 型数据。

在数字末尾加一个字母 L 就表示 long 型

fseek(fp,100L,0);
//将文件位置标记 向前 移动到 文件开头 100字节处
fseek(fp,50L,1);
//将文件位置标记 向前 移动到从 当前位置 50字节处
fseek(fp,-10L,2);
//将文件位置标记从文件末尾出向后移动10个字节

注意
一定要记住加 L 表示 long 型数据

ftell 函数

作用:获取流式文件中文件位置标记的当前位置
因为位置总是变来变去的嘛,所以我们经常记不住当前位置,ftell 函数就可以帮我们把当前位置保存下来。如果调用函数出错,则返回-1L

i=ftell(fp);
if(i==-1L){
printf("Error!\n");
}

尾巴

这是我的个人学习笔记,主要是应付考研复习使用,充斥着一些吐槽和个人观点,并不严谨,欢迎大家参考、指正。