【C语言】文件操作详解3(文件的随机读写和其他补充)

【C语言】文件操作详解3(文件的随机读写和其他补充)

前言:
书接上回,由于文章过长,所以分了三篇文
若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持
谢谢大家 ! ! !

上期给大家介绍了文件的顺序读写操作
这期我们就来聊聊文件的随机读写操作

一、文件的随机读写操作

文件的随机读写,顾名思义
在读写时可以定位到想要读写的地方

其中有几个函数,我来一一讲解

1.fseek函数(定位文件光标)

根据文件指针的位置和偏移量来自行定位文件内容的光标

语法:
int fseek ( FILE * stream, long int offset, int origin );
stream表示流(文件的文件指针)
offset表示当前位置相比于起始位置origin的偏移量
origin表示起始位置

(1)origin

表示起始位置

origin有且仅有三种选项:

  1. SEEK_SER文件的起始位置
  2. SEEK_CUR文件指针的当前位置
  3. SEEK_END文件的末尾

(2)offset

表示当前位置相比于起始位置origin的偏移量

且注意,offset可为负数
正数就向右偏移,负数就向左偏移

如图解:

代码演示:
先将一串字符写入文件中,再用fseek来自行定位文件内容光标
最后打印出光标后的字符

(写入1234567890):

运行代码,将内容光标定位到文件的起始位置向右偏移4个字符:

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "r");
    //打开文件

    if (pf == NULL)
    {
        perror("fopen");
        //打印出错误信息
        return 0;
        //返回状态码 1 表示异常退出
    }

    fseek(pf, 4, SEEK_SET);
    //将内容光标定位到文件的起始位置向右偏移4个字符

    char ch;
    while ((ch=fgetc(pf)) != EOF)
    {
        printf("%c", ch);
    }

    printf("\n\n");
    fclose(pf);//关闭文件
    pf = NULL;//置为NULL空指针

    return 0;
}

运行结果:

通过运行结果,我们可以看到,我们只打印了起始位置后4位的字符,前4个字符跳过了
这就是因为fseek可以自行定位文件内容的光标
这里我定位到了距离文件起始位置偏移量为+4的位置,也就是从5开始打印

2.ftell(找到文件光标)

返回文件的内容光标相较于文件起始位置的偏移量
可以知道文件内容的光标现在在哪里

语法:
long int ftell ( FILE * stream );
stream表示流(文件的文件指针)

代码演示:
现在,先将文件的光标借助fseek函数定位到距离文件起始位置偏移量为+4的位置处,再用ftell函数得出文件的内容光标相较于文件起始位置的偏移量

代码如下:

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "r");
    //打开文件

    if (pf == NULL)
    {
        perror("fopen");
        //打印出错误信息
        return 0;
        //返回状态码 1 表示异常退出
    }

    fseek(pf, 4, SEEK_SET);
    //将内容光标定位到文件的起始位置向右偏移4个字符储处

    int ret=ftell(pf);
    //得出文件的光标相较于文件起始位置的偏移量
    printf("%d", ret);
    //打印出偏移量

    printf("\n\n");
    fclose(pf);//关闭文件
    pf = NULL;//置为NULL空指针

    return 0;
}

运行结果:

果然,偏移量是4
所以,ftell函数可以知道文件内容的光标现在在哪里,并返回文件的内容光标相较于文件起始位置的偏移量从而更好读写

3.rewind(使光标返回起始位置)

让文件的光标返回起始位置

语法:
void rewind ( FILE * stream );
stream表示流(文件的文件指针)

代码演示:
现在,先用fputs先输出一些数据,再用rewind让光标返回起始位置,接着用fputs再次输出一些数据,最后观察文件内容

代码:

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

int main()
{
    FILE* pf = fopen("test.txt", "w");
    //打开文件

    if (pf == NULL)
    {
        perror("fopen");
        //打印出错误信息
        return 0;
        //返回状态码 1 表示异常退出
    }

    fputs("12345678", pf);
    //先输出一些数据

    rewind(pf);
    //让光标返回起始位置

    fputs("xxxx", pf);
    //再次输出数据

    printf("\n\n");
    fclose(pf);//关闭文件
    pf = NULL;//置为NULL空指针

    return 0;
}

运行结果:

显然,在rewind的作用下,文件的内容光标先返回到了文件的起始位置,然后再输出"xxxx"数据

所以,rewind可以让文件的光标返回起始位置,便于输出

二、文件读写结束时的判定

文本的读写在这一期以及上一期给大家讲完了
那么,该如何判定文件读取是否结束呢?

这里我分为两种情况:

1.判定文本文件是否读取结束

判断返回值是否为EOF(fgetc) 或者NULL(fgets)

fgetc函数文件读取结束时,会返回EOF
fgets函数文件读取结束时,会返回NULL

2.判定二进制文件是否读取结束

判断返回值是否小于实际要读取个数

由于fwritefread 函数的返回值是实际输入或输出的总元素个数

(上节讲过不知道的可以去看看)
所以,可以通过比较返回值和实际要读取个数的大小
若 返回值 == 实际要读取个数 则读取结束
否则未读取结束

3.例题分析(拷贝文件)

光讲肯定是不行的,要有代码的实践才行,这里给大家讲解一道例题吧

问:如何将date.txt文件中的内容拷贝到copy_date.test文件中去

先在date.txt文件中写入一些字符

然后运行代码
注意:
因为date.test我们要输入数据,故用" r "只读的方式
因为copy_date.test我们要输出数据,故用" w "只写的方式

c 复制代码
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

void copy(FILE* p1, FILE* p2)//定义一个拷贝函数
{
	char ch;
	int sum = 0;
	while ((ch = fgetc(p1)) != EOF)//当文件读取结束时停止
	{
		fputc(ch, p2);//一个字符一个字符拷贝
	}
}

int main()
{
	FILE* p1 = NULL;//初始化文件指针变量
	FILE* p2 = NULL;//初始化文件指针变量

	if ((p1 = fopen("date.txt", "r")) == NULL)//打开被拷贝的文件
	{
		printf("文件打开失败,未找到该文件\n\n");
		return 0;
	}
	p2 = fopen("copy_date.test", "w");//打开要拷贝的文件

	copy(p1, p2);//调用拷贝函数

	fclose(p1);//最后关闭文件
	p1 = NULL;//置空指针
	fclose(p2);
	p2 = NULL;

	return 0;
}

运行结果:
观察copy_date.test文件内容是否完成拷贝


结果显而易见,完成了拷贝

结语

本期资料来自于:

https://legacy.cplusplus.com/

OK,所有的文件操作详解到这里就结束了
由于文章过长,所以分了三篇文

若内容对大家有所帮助,可以收藏慢慢看,感谢大家支持
本文有若有不足之处,希望各位兄弟们能给出宝贵的意见。谢谢大家!!!
新人,本期制作不易希望各位兄弟们能动动小手,三连走一走!!!
支持一下(三连必回QwQ)

相关推荐
java修仙传33 分钟前
力扣hot100:最长连续序列
算法·leetcode·职场和发展
Pluchon38 分钟前
硅基计划4.0 算法 记忆化搜索
java·数据结构·算法·leetcode·决策树·深度优先
CoderYanger39 分钟前
动态规划算法-简单多状态dp问题:18.买卖股票的最佳时机Ⅳ
开发语言·算法·leetcode·动态规划·1024程序员节
Less is moree41 分钟前
2.C语言文件操作(一):fgetc(),fgets(),fread的区别
c语言·开发语言·算法
CoderYanger41 分钟前
动态规划算法-简单多状态dp问题:13.删除并获得点数
java·开发语言·数据结构·算法·leetcode·动态规划·1024程序员节
浅川.2543 分钟前
xtuoj Balls
数据结构·算法
分布式存储与RustFS44 分钟前
云原生基石:实战RustFS on Kubernetes,构建高可用存储架构
算法·云原生·kubernetes·对象存储·高可用·企业存储·rustfs
ohnoooo91 小时前
C++ STL库常用容器函数
java·开发语言
顾人间讥诘1 小时前
卡特兰数及相关应用场景
算法