【维生素C语言】第十六章 - 文件操作(下)_fseek(pf, -3, seek_cur);

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

在文件操作(上)中,我们讲了文件的打开和关闭和文件的顺序读写,还有对流(stream)进行一个简单的讲解。本章将对文件的随机读写、文本文件和二进制文件、文件读取结束的判定,以及文件缓冲区进行讲解。

🚪 传送门:文件操作(上)


一、文件的随机读写

0x00 文件指针定位函数 fseek

📚 介绍:根据文件指针的位置和偏移量来定位指针。

1️⃣ 参数:offset 是偏移量。

2️⃣ 参数:origin 是起始位置,有三种选项:

SEEK_CUR  当前文件指针的位置开始偏移。

SEEK_END  文件的末尾位置开始偏移。

SEEK_SET 文件的起始位置开始偏移。

💬 代码演示:手动创建一个文件,打开文件随便写点内容

#include <stdio.h>

int main(void) {
    FILE* pf = fopen("test6.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);

    // 关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}

❓ 如果我想得到 a a b,该怎么做?

💡 我们可以试着使用 fseek 函数:

#include <stdio.h>

int main(void) {
    FILE* pf = fopen("test6.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);

    // 调整文件指针
    fseek(pf, -1, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为-1,向前移动1个单位
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);

    // 关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}

💬 用 SEEK_SET ,打印 a d e

#include <stdio.h>

int main(void) {
    FILE* pf = fopen("test6.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);

    // 调整文件指针
    fseek(pf, 3, SEEK_CUR); // SEEK_SET为文件的起始位置,偏移量为3,向后移动3个单位
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);

    // 关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}

💬 用 SEEK_END ,打印 a e f

#include <stdio.h>

int main(void) {
    FILE* pf = fopen("test6.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 读取文件
    int ch = fgetc(pf);
    printf("%c\n", ch);

    // 调整文件指针
    fseek(pf, -2, SEEK_END); // SEEK_END为当前文件末尾位置,偏移量为-2,向前移动2个单位
    ch = fgetc(pf);
    printf("%c\n", ch);
    ch = fgetc(pf);
    printf("%c\n", ch);

    // 关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}
0x01 返回偏移量函数 ftell

📚 介绍:返回文件指针相对于起始位置的偏移量。

💬 代码演示:ftell 的使用方法

#include <stdio.h>

int main(void) {
    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;
}

🚩 运行结果如下:

0x02 文件指针回到起始位置函数 rewind

📚 介绍:rewind(意为倒带,磁带倒带),设置文件位置为给定流 stream 的文件的开头,让文件指针回到起始位置。

💬 代码演示:利用rewind 函数让文件指针回到起始位置

#include <stdio.h>

int main(void) {
    FILE* pf = fopen("test6.txt", "r");
    if (pf == NULL) {
        perror("fopen");
        return 1;
    }

    // 调整文件指针
    fseek(pf, 5, SEEK_CUR); // SEEK_CUR为当前文件指针位置,偏移量为5,向后移动5个单位

    // 返回偏移量
    int loc = ftell(pf);
    printf("fseek调整文件指针后:%d\n", loc); // 6

    // 让文件指针回到起始位置
    rewind(pf);

    // 再次返回偏移量,看看是不是回到起始位置了
    loc = ftell(pf);
    printf("使用rewind后:%d\n", loc); // 6

    // 关闭文件
    fclose(pf);
    pf = NULL;

    return 0;
}

🚩 运行结果如下:

二、文本文件和二进制文件

0x00 引入

再上一节中,我们已经对文本文件二进制文件开了个头,在这里我们将进行详细的探讨!

📚 根据数据的组织形式,数据文件被称为文本文件或者二进制文件。

0x01 文本文件

❓ 什么是文本文件?

📚 如果要求在外存上以 ASCII 码的形式存储,则需要在存储之前进行转换。以 ASCII 字符的形式存储的文件,就是文本文件。

0x02 二进制文件

❓ 什么是二进制文件?

📚 数据在内存中以二进制的形式存储,如果不加以转换地输出到外存,就是二进制文件。

0x03 数据在文件中的存储方式

❓ 一个数据在文件中是如何存储的呢?

📚 存储方式如下:

① 字符一律以 ASCII 形式存储。

② 数值型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储

🌰 举个简单的例子:比如整数10000,如果以 ASCII 码的形式形式输出到磁盘,则磁盘中占用5个字节(每个字符占1个字节)。而如果以二进制的形式输出,则在磁盘上只占4个字节。

💬 测试代码:

#include <stdio.h>

int main(void) {
    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;
}

🚩  (代码成功运行)

💡 我们来使用非常强大的【宇宙第一编辑器】Visual Studio(2013版本)来打开我们的二进制文件 test6.txt ,详细步骤如下:

🔑 最后,我们来检测一下 10000 是不是 10 27 00 00

🔺 总结:文本文件和二进制文件的存储方式

① 文本文件:将内存里的数据转换成 ASCII 码值的形式存储到文件中。

② 二进制文件:将内存里的二进制数据不加任何转化直接存储到二进制文件中。

三、文件读取结束的判定

读文件读到什么时候才算结束,是个非常值得我们探讨的问题。

0x00 经常被错误使用的 " feof 函数 "

📚 介绍:在文件结束时,判断文件因为何种原因导致文件结束的函数,判断是因为读取失败而结束,还是因为遇到文件尾而结束。如果文件结束,则返回非0值,否则返回0。

❌ 错误用途:feof 函数是个经常被错误使用的一个函数。在文件读取过程中,不能用 feof 函数的返回值直接判断文件是否结束!feof 函数绝对不是用来判断文件是否结束的函数!feof 不是用来判定文件是否结束了的,还是在文件已经结束时,判断是什么原因导致文件结束的。

✅ 正确用途:当文件读取结束时,判断是因为读取失败而结束,还是因为遇到文件尾而结束。

💬 代码演示:feof 的用法:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int ch = 0; // 注意:为int型而非char,要求处理EOF
    FILE* pf = fopen("test.txt", "r");
    if (!pf) {  // pf == NULL
        perror("fopen");
        return EXIT_FAILURE; // 符号常量EXIT_FAILURE,表示没有成功地执行一个程序
    }


![img](https://img-blog.csdnimg.cn/img_convert/d081d58bded6beff45e8d836b6e67509.png)
![img](https://img-blog.csdnimg.cn/img_convert/9f7705c77e07563c089bfca2f0f92428.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

f = fopen("test.txt", "r");
    if (!pf) {  // pf == NULL
        perror("fopen");
        return EXIT_FAILURE; // 符号常量EXIT_FAILURE,表示没有成功地执行一个程序
    }


[外链图片转存中...(img-37ylMKxb-1715792273699)]
[外链图片转存中...(img-AooKtiD8-1715792273699)]

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以添加戳这里获取](https://bbs.csdn.net/topics/618668825)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值