开发者

C语言文件随机读写的完全指南

目录
  • 导读
  • 一、fseek
  • 二、ftell
    • 2.1 函数介绍
    • 2.2 函数使用
  • 三、rewind
    • 3.1 函数介绍
    • 3.2 函数使用
  • 四、fgetpos
    • 4.1 函数介绍
    • 4.2 fpos_t
  • 五、fsetpos
    • 5.1 函数介绍
    • 5.2 函数使用
    • 5.3 函数比较
      • 5.3.1 相同点
      • 5.3.2 不同点
  • 结语

    导读

    无论是字符级的 fgetc/fputc,字符串操作的 fgets/fputs,还是格式化的 fscanf/fprintf,以及二进制的 fread/fwrite,这些函数都遵循着"从头到尾、依次处理"的顺序读写模式。

    然而,在实际编程中,我们常常需要更灵活的文件操作方式。今天,我们将进入文件操作的另一个重要领域——随机读写,学习如何精准控制文件中的读写位置。让我们开始探索以下五个核心函数:

    • fseek —— 设置文件中的位置指示器位置
    • ftell —&mdaphpsh; 获取文件中的位置指示器位置
    • rewind —— 重置文件中的位置指示器位置
    • fgetpos —— 获取文件中的位置指示器位置
    • fsetpos —— 设置文件中的位置指示器位置

    一、fseek

    C语言文件随机读写的完全指南

    上图给出了函数用法的介绍,我们可以看到该函数不仅能够对文本文件使用,还可以对二进制文件使用;

    C语言文件随机读写的完全指南

    上图给我们介绍了函数的三个参数与返回值,从这两张图片介绍中,我们可以了解该函数的使用方法:

    • 向函数中传入3个参数
      • stream :指向识别流的 FILE 对象指针
      • offset :文件中光标的位置
        • 二进制文件中:从 origin&nbsandroidp;的参考值中偏移的字节数
        • 文本文件中:0 或者由 ftell 函数获取的返回值
      • origin :为 offset 参考的位置
        • SEEK_SET : 文件开头
        • SEEK_CUR :文件指针的当前位置
        • SEEK_END :文件末尾
    • 函数会将与流关联的文件内部的光标设置为一个新位置:
      • 二进制文件:新位置由 origin 的参考位置的偏移量 offset 定义
      • 文本文件:新位置为 0 或者由先前调用 ftell 函数时的返回值,并且 origin 的参考值必须为 SEEK_SET ,即文件开头;
      • 当函数在这些参考值之外调用其他值,是否支持还取决于特定的系统和库的实现。即若当前系统支持,那此时的使用方法无法移植。
    • 函数在完成设置后,会给出相应的返回值:
      • 设置成功,则函数返回 0
      • 设置失败,则函数返回非零值
      • 如果发生读取或写入错误,则函数会设置错误指示器(ferror

    从用法中我们可以看到,该函数的使用与 ftell 函数是分不开的,因此我们下面直接来看一下 ftell 函数应该如何使用;

    二、ftell

    2.1 函数介绍

    C语言文件随机读写的完全指南

    该函数的使用方法为:

    • 向函数中传入一个参数:
      • stream :指向识别流的 FILE 对象指针
    • 函数会从流中获取当前位置指示器的值
      • 成功时,则将当前值返回
      • 失败时,则返回 -1L ,并将 errno 设置为系统的特定正值

    2.2 函数使用

    该函数的使用我们可以简单的理解为,函数会获取文件中的光标位置:

    • 当文件为二进制文件时,函数的返回值为文件光标从文件开头开始的偏移量
    • 当文件为文本文件时,函数的返回值可能没有实际意义,但是仍可在调用 fseek 时作为函数参数,让 fseek 将光标的位置恢复到当前位置

    现在对于 fseek 和 ftell 这两个函数我们就能够理解为:

    • ftell 用于获取文件中的光标位置
    • fseek 用于设置文件中的光标位置

    接下来我们就可以尝试着使用这两个函数了:

    void test1() {
    	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r+");
    	if (pf == NULL) {
    		perror("fopen");
    		return;
    	}
    
    	// 通过 ftell 获取文件中的光标当前位置
    	long int index = ftell(pf);
    	// 检查返回值
    	if (index == -1L) {
    		perror("ftell");
    		fclose(pf);
    		pf = NULL;
    		return;
    	}
    
    	// 通过 fgetc 读取当前位置的文本信息
    	int ch = fgetc(pf);
    	while (ch != EOF) {
    		printf("ch = %c\n", ch);
    		ch = fgetc(pf);
    	}
    
    	// 通过 fseek 设置文件中的光标位置
    	int set = fseek(pf, index, SEEK_SET);
    	// 由于我们打开的为文本文件,因此 origin 的值必须为文件开头(SEEK_SET)
    
    	if (set != 0) {
    		perror("fseek");
    		fclose(pf);
    		pf = NULL;
    		return;
    	}
    
    	// 再一次读取当前位置的元素
    	ch = fgetc(pf);
    	printf("ch = %c\n", ch);
    
    	fclose(pf);
    	pf = NULL;
    }
    

    这里的测试代码逻辑比较简单:

    • 先通过 ftell 记录文件当前的光标起始位置
    • 通过 fgetc 进行内容读取,直到光标移动到文件末尾
    • 之后通过 fseek 重新设置光标的位置
    • 最后再一次通过 fgetc 来读取当前位置的内容

    下面我们就来运行以下该测试代码:

    C语言文件随机读写的完全指南

    从测试结果中可以看到,文件刚打开时,光标的位置为文件开头,当我们通过 ftell 记录了此时的位置后,我们通过 fgetc 移动了光标,不管光标最后在哪里,我们都可以通过 fseek 函数将光标设置到最初我们记录的位置;

    那可能有朋友会问,如果我们在记录光标的起始位置时,光标并不在文件开头,这时我们需要将光标重置到文件开头,应该怎么办呢?

    此时有两种办法:

    • 通过将 offset 参数值置为 0 ,即 int set = fseek(pf, 0, SEEK_SET);
    • 通过 rewind 函数重置光标位置

    接下来,我们就来看看 rwind 函数的具体用法;

    三、rewind

    3.1 函数介绍

    C语言文件随机读写的完全指南

    该函数的用法如下:

    • 向函数中传入一个参数:
      • stream :指向标识流的 FILE 对象指针
    • 函数会清除流中的文件末尾内部指示器错误内部指示器,并将文件内部的位置指示器设置为文件开头

    3.2 函数使用

    该函数简单的理解就是用于重置文件内部的光标位置。接下来我们就来对其进行测试:

    void test2() {
    	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r+");
    	if (pf == NULL) {
    		perror("fopen");
    		return;
    	}
    
    	// 通过 fgetc 先读取一定的文本信息
    	for (int i = 0; i < 3; i++) {
    		int ch = fgetc(pf);
    		printf("ch = %c ", ch);
    	}
    	printf("\n");
    
    	// 通过 ftell 获取文件中的光标当前位置
    	long int index = ftell(pf);
    	// 检查返回值
    	if (index == -1L) {
    		perror("ftell");
    		fclose(pf);
    		pf = NULL;
    		return;
    	}
    
    	// 通过 fgetc 读取当前位置的文本信息
    	int ch = fgetc(pf);
    	while (ch != EOF) {
    		printf("ch = %c ", ch);
    		ch = fgetc(pf);
    	}
    	printf("\n");
    
    	// 通过 fseek 设置文件中的光标位置
    	int set = fseek(pf, index, SEEK_SET);
    	// 由于我们打开的为文本文件,因此 origin 的值必须为文件开头(SEEK_SET)
    
    	if (set != 0) {
    		perror("fseek");
    		fclose(pf);
    		pf = NULL;
    		return;
    	}
    
    	// 再一次读取当前位置的元素
    	ch = fgetc(pf);
    	printf("ch = %c\n", ch);
    
    	// 通过 rewind 重置光标位置
    	rewind(pf);
    
    	// 再一次读取当前位置的元素
    	ch = fgetc(pf);
    	printf("ch = %c\n", ch);
    
    	fclose(pf);
    	pf = NULL;
    }
    

    我们此时的测试逻辑很简单:

    • 文件在打开时,光标会位于文件开头
    • 首先,我们通过 fgetc 读取数据来移动光标
    • 完成写入后,通过&nbsCAlTxoyUlFp;ftell 来记录光标此时的位置
    • 接下来,我们继续通过 fgetc 读取数据,进一步移动光标
    • 之后,我们再通过 fseek 来恢复光标的位置
    • 最后,我们再通过 rewind 来重置光标的位置

    下面我们就来对其测试一下:

    C语言文件随机读写的完全指南

    可以看到,当我们使用 rewind 后,光标的位置就从我们最开始记录的 l 处重置为了文件开头 H 处。

    因此当我们在对文件进行操作时,如果我们需要重置光标的位置,我们就可以通过 rewind 实现。

    四、fgetpos

    4.1 函数介绍

    C语言文件随机读写的完全指南

    该函数的用法如下所示:

    • 向函数中传入两个参数:
      • stream :指向标识流的 FILE 对象指针
      • pos :指向 fpos_t 对象指针
    • 函数会将从 stream 中获取到的当前位置信息填入到 pos 中
      • 成功时,函数返回 0
      • 发生错误时,errno 会被设置为平台特定的正值,并且函数返回一个非零值

    4.2 fpos_t

    在函数的用法介绍中,我们看到了一个新的类型:fpos_t 。那么在使用该函数前,我们先来认识一下这个新的类型:

    C语言文件随机读写的完全指南

    该类型就是专门用于记录文件中的光标位置的类型,该类型的变量中存储的信android息,通常是通过 fgetpos 函数进行填充,并且其变量中的信息不能直接读取,只能够在调用 fsetpos 时,作为参数使用。

    那也就是说,fgetposfsetpos 这两个函数应该搭配起来使用,那么接下来我们就一起来看看如何 fsetpos 的具体用法;

    五、fsetpos

    5.1 函数介绍

    C语言文件随机读写的完全指南

    该函数的用法如下所示:

    • 向函数中传入两个参数:
      • stream :指向标识流的 FILE 对象指针
      • pos :指向 fpos_t 对象指针
    • 函数会将 stream 的当前位置恢复到 pos 中
      • 成功时,函数返回 0
      • 发生错误时,errno 会被设置为平台特定的正值,并且函数返回一个非零值

    5.2 函数使用

    该函数的用法我们可以简单的理解为,将文件中的光标位置恢复到 pos 中存储的位置。

    这里需要注意的是,pos_t 的对象中存储的信息只能通过 fgetpos 获取,我们无法直接对其进行赋值操作!!!

    接下来我们就来尝试着使用一下这两个函数:

    void test3() {
    	FILE* pf = fopen("C:\\Users\\LIQIAN\\Desktop\\data.txt", "r");
    	if (pf == NULL) {
    		perror("fopen");
    		return;
    	}
    
    	// 通过 fgetc 读取数据来移动光标
    	for (int i = 0; i < 3; i++) {
    		int ch = fgetc(pf);
    		printf("ch = %c\n", ch);
    	}
    	printf("\n");
    	// 记录光标位置变量
    	fpos_t pos;
    
    	// 通过 fgetpos 获取当前光标位置
    	int get = fgetpos编程客栈(pf, &pos);
    
    	// 通过 fgetc 移动光标
    	int ch = fgetc(pf);
    	while (ch != '!') {
    		printf("ch = %c\n", ch);
    		ch = fgetc(pf);
    	}
    
    	printf("\nch = %c\n", ch);
    
    	// 通过 fsetpos 来恢复光标位置
    	int set = fsetpos(pf, &pos);
    	
    	ch = fgetc(pf);
    	printf("\nch = %c\n", ch);
    
    	fclose(pf);
    	pf = NULL;
    }
    

    这一次我们测试的逻辑与前面的逻辑一致:

    • 先通过 fgetc 来移动光标
    • 再通过 fgetpos 来获取光标位置信息
    • 之后再一次通过 fgetc 来移动光标
    • 最后通过 fsetpos 来设置光标位置

    下面我们就来测试一下:

    C语言文件随机读写的完全指南

    可以看到,函数 fgetposfsetpos 二者配合起来使用,同样能够达到光标定位与设置的效果。

    现在问题来了,这两个函数与前面我们介绍的 ftellfseek 之间有什么不同呢?

    5.3 函数比较

    5.3.1 相同点

    不管是 ftell 与 fseek 的搭配使用,还是 fgetpos 与 fsetpos 的搭配使用,他们都是用来完成两件事:

    • 记录光标位置
    • 设置光标位置

    5.3.2 不同点

    这二者之间不同的地方在于—— 记录光标位置的方式不同

    • ftell 是通过 long int 类型的变量来记录光标的位置
    • fgetpos 则是通过 fpos_t 类型的变量来记录光标位置

    因此,这就导致了二者能够处理的文件大小有所区别:

    • 当光标的位置值大于 long int 时,我们再通过 ftell 来记录光标的位置就会出现问题
    • 由于 fgetpos 是通过 fpos_t 来记录,因此,我们不需要考虑光标的位置是否会存在溢出的情况

    也就是说,当我们处理大文件时,我们选择使用 fgetposfsetpos 会更加保险一点。

    结语

    通过今天的学习,我们深入掌握了C语言中实现文件随机读写的五个核心函数。让我们简单回顾一下本篇的重要内容:

    函数功能总结

    • fseek:精确定位文件光标,支持三种参考位置(文件头、当前位置、文件尾)
    • ftell:获取当前光标位置,为 fseek 提供定位依据
    • rewind:快速重置光标到文件开头,并清除错误指示器
    • fgetpos:使用fpos_t类型安全记录光标位置
    • fsetpos:与 fgetpos 配合,精准恢复光标位置

    关键区别:

    • ftell/fseek 使用 long 类型,适合一般文件操作
    • fgetpos/fsetpos 使用 fpos_t 类型,更适合大文件处理

    实践价值

    掌握了这些函数,我们就能在文件中自由"穿梭",实现高效的随机访问,为复杂文件操作打下坚实基础。

    以上就是C语言文件随机读写的完全指南的详细内容,更多关于C语言文件随机读写的资料请关注编程客栈(www.devze.com)其它相关文章!

    0

    上一篇:

    下一篇:没有了

    精彩评论

    暂无评论...
    验证码 换一张
    取 消

    最新开发

    开发排行榜