基础IO的理解与操作 - fd
目录
一、理解Linux下一切皆文件
相信诸位学习过Linux的小伙伴对这句话不陌生吧。Linux下一切皆文件,也就是说在冯诺依曼体系下的任何东西,均可视为文件?为什么能这么说呢?
你还记得最初从电脑建立的那个空白文件夹吗?我们从那里说起吧。


1.文件的理解
普通文件的理解
文件是什么?
文件属于文件的一种,与普通文件载体不同,文件是以硬盘为载体存储在计算机上的信息集合。
文件可以是文本文档、图片、程序等等。文件通常具有点+三个字母的文件扩展名,用于指示文件类型(例如,图片文件常常以JPEG格式保存并且文件扩展名为.jpg)。(来自百度百科)
这就是我们平时所能理解的文件,一个文件通常包含它的属性和内容。
文件 = 内容 + 属性
那么这里的属性也是这个文件的数据吗?当然是,你想想,一个空白文件,在磁盘上占空间吗?自然占,属性需要占用空间,里面存放关于此文件的一些基础信息(创建时间,修改时间,文件名.....)
磁盘上存放着文件,我们难免会对文件进行操作。想一想,我们对文件有什么操作呢?
对文件的所有操作:1.对内容 2.对属性
对内容是经常性的,属性也是如此。
对文件的操作
那么在语言中(比如C语言)我们访问文件并且修改的本质又是什么呢?
我们可以顺着如下思路进行想象:
首先,文件是放在磁盘上的。
我们利用程序去访问磁盘,该C语言程序经过编译后形参exe(可执行文件),运行加载入内存变成进程。
进程进行访问文件->通过操作系统的接口进行访问。
我们可以在观察一下冯诺依曼体系:

要向磁盘进行写入,即输出设备,那么只有执行CPU也就是操作系统才有权利进行写入。(操作系统是硬件的管理者)(PS:想要更进一步了解Linux操作系统和进程之间的关系可以看一下这篇文章哦:【Linux】从冯诺依曼体系到初识Linux下的进程_柒海啦的博客-CSDN博客)
普通用户想要写入,那么就必须要操作系统提供的接口才能对文件进行操作。
语言接口和操作系统接口的区别
那么,从这里开始,就要分清楚,为什么语言会提供访问文件的接口而不直接用操作系统的系统调用了。
1.语言上对此进行封装,为了让接口更加贴切语言,更加好用 -> 导致了不同的语言级别的文件访问接口(都不一样),但是都是用的系统接口。系统接口使用成本高,不贴切语言。
2.跨平台 -- 如何语言不提供对文件的系统接口的封装,那么所有的文件操作,就必须使用OS的接口 -- 这样写出来的代码不具备跨平台性!-- 语言就把所有OS的接口封装实现,条件编译,动态裁剪即可。
我们学习系统调用接口的目的在于更好的了解底层访问文件的步骤,虽然每一种语言的文件io部分的接口不同,但是本质都是通过操作系统去访问文件的,只要本质不变,我们就能更加理解文件IO了。
理解广义文件
那么,我们来回忆一下C/C++内<stdio.h><iostream>文件里的接口:
printf/cout 向显示屏写入数据
scanf/cin 向键盘读取数据
写入和读取,是不是一种文件操作呢?
现在,对文件我们可以进行一个感性的理解:
语言对文件的操作就是对文件内容的读和写操作(read、write),上面的printf/cout就是程序在对显示屏进行写入数据,显示屏才能显示出来,而scanf/cin则是程序从键盘中读取数据,存放入此进行的地址内存空间内。但是,这里的显示屏和键盘难道不是硬件吗?是的,也是文件。
文件的读和写:
普通文件- > fopen/fread -> 你的进程内部(内存)-> fwrite -> 文件中
(input) (output)
那么在整理一下什么叫文件:
站在系统的角度,能被input,output的设备就叫做文件!
狭义的文件:普通的磁盘的文件
广义的文件:显示器、键盘、网卡、声卡、显卡、磁盘.....基本所有的外设,都可被称作文件
那么,现在我们来简单的回忆一下C语言接口来操作文件。
2.利用C接口操作文件
打开文件
首先,我们需要打开文件:
头文件依赖:#include <stdio.h>
函数原型:FILE *fopen(const char *path, const char *mode);
path:
绝对路径/相对路径
mode:
打开方式:w/w+/r/r+/a/a+ ...
w:只写,清空当前文件内容(没有会创建此文件(当前路径下创建对应文件名))
r:只读。
+:可读可写
a:每次在此文件数据末尾进行追加(没有会创建此文件)
使用FILE对象接收(FILE实际上是C语言里的一个结构体)
这里可以稍微谈一下路径这一说法,如何理解此进程的当前路径呢?
比如,我当前写了一个程序,现在正在被运行,我们可以利用命令:ls /proc/pid -l 来查看此进程的相关属性:

如上图所示,其中进程属性cwd为当前工作目录,exe为此程序路径。
关闭文件
打开文件后,如何关闭呢?关闭就非常简单:
int fclose(FILE *fp);
fp就是对应的文件对象,此时该文件就不会在从内存中读取到了。
写操作output
(下面没有列举全部,只是举例部分)
依赖头文件:<stdio.h>
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
描述:
返回值:写入成功,返回写的项数,单位为字节数。发生错误或者文件末尾到达时,返回值是简短的项目计数(或0)
ptr 写入的字符串
size:每个数据的大小(单位字节)
nmemb:数据个数
stream:被写入的文件。
int fputc(int c, FILE *stream); 写入一个字符
int fputs(const char *s, FILE *stream); 写入一个字符串。成功返回非负数,否则返回EOF。
int fprintf(FILE *stream, const char *format, ...);
成功时,返回输入字符数,遇到错误返回负数
现在我们利用前面的打开文件和写操作来具体利用代码实现一下:
比如,现在我们想要对当前路径下test.txt文件输入Hello,Linux!。没有的话就创建,你来试试吧~
#include <stdio.h> #include <string.h> int main() {FILE* fp = fopen("test.txt", "w+"); // 使用绝对路径来进行查找,读写操作,没有会进创建对应文件,有会将其数据清空 const char* ptr = "Hello, Linux!\n"; // 输入我们想要写入的字符串 fwrite(ptr, 1, strlen(ptr), fp); // 输出字符串 每个数据大小 多少个数据 目标写入文件 fclose(fp); // 不要忘记关闭文件哦 return 0;}此时就可以发现在当前工作目录下会存在一个test.txt文件,我们将它打印出来就可以发现数据已经写入啦:


其余接口也可以按照如上的操作,这里特别的演示一下和
原创不易,完成人机校验,阅读全文