【看完就会】零基础学习文件操作

本文详细介绍了文件在程序中的重要性,区分了程序文件和数据文件,探讨了二进制文件和文本文件的区别,涉及流和标准流的概念,展示了文件的打开、关闭、顺序和随机读写方法,以及文件结束判定和文件缓冲区的作用。

一、为什么使用文件?

一般来说,我们所写的程序代码的数据都是储存在电脑的内存当中。
但是,当我们退出程序的话,内存就会回收,我们的数据就会丢失。等再次运行程序,是看不到上次程序的数据的。
这个时候我们就认识到了文件的重要性:将数据进行持久化的保存


二、什么是文件?

🔺硬盘(磁盘)上的文件是文件

🔺但是在程序设计中我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)

1.1 程序文件

程序文件包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境后缀为.exe)

1.2 数据文件

🔺文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,或者输出内容的文件。
🔺本章讨论的时数据文件
🔺在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上
🔺其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据上把数据读取到内存中使用,这里到处理的就是磁盘上文件。

2.3 文件名

1.一个文件要有一个唯一的文件标识,一边用户识别和应用。
2.文件名包含三部分:文件路径+文件名主干+文件后缀
例如:c:\code\test.txt
为了方便起见,文件标识常被称为文件名


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

★根据数据的组织形式,数据文件被称作为文本文件或者二进制文件
★数据在内存中以二进制的形式储存,如果不加转换的输出到外存,就是二进制文本。
★如果要求在外存上以ASCLL码的形式储存,则需要在存储前转换。以ASCLL字符的形式储存的文件就是文本文件

一个数据在内存中是以什么样的方式存储呢?

  1. 字符一律以ASCLL形式存储,数据型类型既可以用ASCLL形式存贮,也可以用二进制形式存储。
  2. 如果有整数10000,如果以ASCLL码的形式输出到磁盘,则磁盘中占用5个字节(每个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节。

在这里插入图片描述


四、文件的打开和关闭

4.1 流和标准流

4.1.1 流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流想象成流淌着字符的河。
C程序针对文件、画面、键盘等的数据输入输出操作都是通过流操作的。
-般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。

4.1.2 标准流

那为什么我们可以从键盘输入数据,直接面向屏幕上输出数据,并没有打开流呢?

那是因为c语言程序再启动的时候,默认打开了3个流
srdin-标准输入流,在大多数的环境中从键盘输入,scanf函数就是从标准输入流中读取数据的。
stdout-标准输出流,在大多数的环境中输出至显示器界面,printf函数就是将这些信息输出到标准输出流中。
sedrr-标准错误流,大多数环境中输出到显示器界面。

这是默认打开三个流,我们使用scanf、printf等函数就可以直接进行输入输出操作的。

srdinscanf
stdoutprintf

(`Θ´):stdin、stdout、stderr三个流的类型是:FILE*,通常成为文件操作

(・・):c语言中,就是通过FILE*的文件指针来维护流的各种操作的。

4.2 文件指针

🔺缓冲文件系统中,关键的概念是文件指针类型,简称文件指针
每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态以及文件当前位置等)。这些信息是保存再一个结构体变量中的。该结构体类型是由系统声明的,取名 ** FILE **

例如:VS2013编译环境提供的 stdio.h头文件中有以下的文件类型声明

struct_iobuf{
    char *_ptr;
    int _cut;
    char *_base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_temfname;
};
typedef struct _iobuf FILE;

不同的c编译器的FILE类型包含的内容不完全相同,但是大同小异
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。
一般都是通过一个FILEd指针来维护这个FILE结构的变量,这样使用起来更加方便。

下面来创建一个变量FILE*的指针变量

FILE* pf;    //文件指针变量

定义pf是一个指向FILE类型数据的指针变量。可以使pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它相关联的文件。

☆for example:
在这里插入图片描述

4.3 文件的打开和关闭

文件再读写之前应该先打开文件,在使用结束之后应该关闭文件

在编写程序的时候,再打开文件的同时,都会返回一个FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

🔺ANSIC规定使用 fopen 函数来打开文件, fclose来关闭文件。

    //打开文件
    FILE* fopen(const char* filename, const char* mode);

    //关闭文件
    int fclose(FILE * stream);

🔺mode表示文件的打开模式,下面都是文件的打开模式:

文件使用方式含义如果指定文件不存在
“r” (只读)为了数据,打开一个已经存在的文本文件出错
“w”(只写)为了数据,打开一个文本文件建立一个新的文件
“a” (追加)向文本文件尾添加数据建立一个新的文件
“rb” (只读)为了数据,打开一个二进制文件出错
“wb”(追加)为了数据,打开一个二进制文件建立一个新的文件
“ab”(追加)向一个二进制文件尾添加数据建立一个新的文件
“r+”(读写)为了读和写,打开一个文本文件出错
“w+”(读写)为了读和写,建立一个新的文件建立一个新的文件
“a+”(读写)打开了一个文件,在文件尾进行续写建立一个新的文件
“rb+”(读写)为了读和写,新建一个新的二进制文件出错
“wb+”(读写)为了读和写,新建了一个新的二进制文件建立一个新的文件
“ab+”(读写)打开一个二进制文件,在文件尾进行读和写建立一个新文件

实例代码

/*fopen fclose example*/
#include <stdio.h>

int main() {
    FILE* pFile;
    //打开文件
    pFile = fopen("myfile.txt", "w");   //如果打开文件失败,返回空指针
    //文件操作
    if (pFile != NULL)
    {
        fputs("fopen example", pFile);
        //关闭文件
        fclose(pFile);
    }
    return 0;
}

五、文件的顺序和读写

5.1顺序读写函数介绍

函数名功能适用于
fgets字符输入函数所有输入流
fputs字符输出函数所有输出流
fgets文本行输入函数所有输入流
fputs文本行输出函数所有输出流
fscanf格式化输入函数所有输入流
fprintf格式化输出函数所有输出流
fread二进制输入文件
fwrite二进制输出文件

上面说的使用与所有输入流一般指的是适用于标准输入流和其他输入流(如文件输入流);所有输入流一般指的是适用于标准输出流和其他输出流(如文件输出流)

5.2对比三组函数

函数名作用
scanf针对标准输入(键盘)的格式化输入函数
printf针对标准输出(屏幕)的格式化的输出函数
fscanf针对所有输入流的格式化输入函数
fprintf针对所有输出流的格式化输出
sscanf从一个字符串中读取一个格式化的数据
sprintf把一个格式化的数据转换成字符串

六、文件的随机读写

6.1 fseek

⭐根据文件指针的位置和偏移量来定位文件指针。(文件内容光标)

int fseek(FILE *stream, long int offset, int origin)
                       //偏移量           //从哪开始偏移

例子:

/*fseek example*/
#include <stdio.h>

int main() {
    FILE* pFile;
    //打开文件
    pFile = fopen("example.txt", "wb");
    fputs("This is an apple.", pFile);
    fclose(pFile);
    return 0;
}

在这里插入图片描述

6.2 ftell

⭐返回文件指针相对于位置的偏移量

long int ftell(FILE *stream);

例子

/*ftell example : getting size of a file*/
#include <stdio.h>

int main() {
    FILE* pFile;
    //打开文件
    long size;
    pFile = fopen("myfile.txt", "rb");
    if (pFile == NULL) {
        printf("打开失败");
    }
    else {
        fseek(pFile, 0, SEEK_END);// non-portable
        size = ftell(pFile);
        fclose(pFile);
        printf("size of myfile.txt:%ld bytes. \n", size);
    }
    return 0;
}

在这里插入图片描述
注:文件的打开都是在编程内存的跟目录里面执行的喔~

6.3 rewind

让文件指针的位置回到文件的起始位置

参数stream是要重新定位的文件流。调用rewind()将文件指针移动到文件开头,但不会清空文件缓冲区。这意味着下一次fread()或fscanf()等函数调用将从文件开头读取数据,而不是从文件指针的当前位置继续读取。

例如,以下代码演示了如何使用:

void rewind(FILE *stream);

例子:

#include <stdio.h>

int main() {
    FILE* fp = fopen("example.txt", "r");
    if (fp == NULL) {
        perror("Error opening file");
        return 1;
    }

    char buffer[50];
    fgets(buffer, sizeof(buffer), fp);
    printf("First line: %s\n", buffer);

    rewind(fp);

    fgets(buffer, sizeof(buffer), fp);
    printf("Second line: %s\n", buffer);

    fclose(fp);
    return 0;
}

在这里插入图片描述

在上面的示例中,我们打开了一个名为example.txt的文件,并使用fgets()函数读取了文件的第一行。然后,我们使用rewind()函数将文件指针重新定位到文件开头,并再次使用fgets()函数读取文件的第一行。注意,第二次读取的数据与第一次相同。最后,我们关闭了文件。


七、文件读写结束的判定

7.1 被错误使用的feof

🔺ferror --> 判断是否遇到错误

牢记:在文件读取过程中,不能用feof函数的返回值直接来判断文件的是否结束
feof的作用是:当文件读取结束的时候,判断是读取结束的原因是否是:遇到文件尾结束

  1. 文本文件读取是否结束,判断返回值是否为 EOFfget),或者NULLfgets

例如:
fgetc判断是否为EOF
fgets判断返回值是否为NULL

  1. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数

例如:
⚪fread判断返回值是否小于要读的个数。


八、文件缓冲区

ANSIC标准采用**“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为程序中每一个正在使用的文件开辟一块“文件缓冲区”**。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定的。

在这里插入图片描述
因为有缓冲区的存在,c语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。 如果不做,可能导致读写文件的问题


<think>好的,用户需要寻找适合零基础学习操作系统的教材或教程。根据提供的引用内容,我需要整理出适合初学者的资源,并结合视频和书籍推荐。 首先,引用[1]提到建议跟着完整的视频教程学习,避免一开始就看复杂的书籍,比如《现代操作系统》。因此,我应该优先推荐视频教程。可能提到的例子包括哈工大的操作系统公开课,或者B站上的入门教程,比如子牙老师的课程。 接下来,引用[2]强调虽然视频适合入门,但需要结合权威书籍。这里需要推荐一些适合初学者的书籍,比如《操作系统导论》或者《现代操作系统》的入门部分,但要注意用户是零基础,可能需要更浅显的书籍。 引用[3]提到子牙推荐手写操作系统的课程,这可能涉及实践项目,适合有编程基础的学习者。因此,可以推荐他的实践课程,但需要说明适合有一定基础后深入学习。 需要确保推荐的资源符合零基础的需求,避免过于复杂。视频教程可能更友好,如哈工大的课程结构清晰,而书籍方面可能需要选择内容较为基础的,比如《操作系统导论》或《Orange'S:一个操作系统的实现》这类结合实践的书籍。 还要考虑用户是否需要中英文资源,但根据引用中的内容,中文资源更合适。可能提到的书籍包括《操作系统真象还原》和《30天自制操作系统》,这些书适合动手实践,但需要评估是否适合零基础。 最后,生成相关问题时要围绕学习路径、视频与书籍的结合、实践项目以及进阶资源展开,确保问题能够帮助用户进一步探索学习操作系统的方法。</think>### 适合零基础学习操作系统的教材与教程推荐 #### 一、视频教程(适合入门阶段) 1. **哈工大《操作系统》公开课** - 特点:从进程管理、内存管理到文件系统逐步讲解,结合实验项目帮助理解核心概念[^1]。 - 学习路径:先观看理论部分,再尝试配套实验(如进程调度算法实现)。 2. **B站子牙《手写操作系统》课程** - 特点:通过实践(如从零编写Bootloader)理解操作系统底层原理,适合对代码实现感兴趣的学习者[^3]。 - 示例项目: ```c // 简单的Bootloader示例 void boot_main() { print("Loading kernel..."); load_kernel_from_disk(); jump_to_kernel(); } ``` #### 二、书籍推荐(结合视频同步学习) 1. **《操作系统导论》(Operating Systems: Three Easy Pieces)** - 优点:以虚拟化、并发、持久化三大主题为核心,语言通俗易懂,提供大量实例。 - 重点章节:第2章(进程与线程)、第18章(页面置换算法)。 2. **《Orange'S:一个操作系统的实现》** - 优点:从汇编开始逐步实现一个简易操作系统,代码注释详细,适合实践型学习者。 - 配套工具:NASM汇编器、Bochs虚拟机。 #### 三、进阶与实践资源 1. **MIT 6.828课程(含实验)** - 内容:通过实现JOS内核学习进程隔离、虚拟内存等高级主题。 - 实验难度:中等偏高,建议学完基础后挑战。 2. **《操作系统真象还原》** - 特点:以问题驱动的方式引导读者探索操作系统设计,涵盖中断处理、文件系统等模块。 #### 四、学习路线建议 1. **第一阶段(1-2个月)** - 目标:掌握进程/线程、内存管理、文件系统等核心概念。 - 方法:视频学习(70%)+ 书籍阅读(30%),完成简单实验(如用Python模拟进程调度)。 2. **第二阶段(2-3个月)** - 目标:动手实现小型操作系统模块。 - 方法:参考《Orange'S》或子牙课程,从Bootloader开始逐步扩展功能。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Reuuse

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值