Linux基础(四)——基础文件IO

1.首先我们来回顾一下C语言里关于文件操作的接口:

1.打开一个文件:
FILE *fopen(const char *path, const char *mode);
//第一个参数为文件名;第二个参数为打开方式
//打开方式的选项有:r,r+,w,w+,a,a+

2.向文件中写数据:
size_t fwrite(const void *ptr, size_t size, size_t nmemb,FILE *stream);
//第一个参数是要写入的内容;第二个参数是要写入内容的大小;
//第三个参数是每次写入几个字节;第四个参数是要把内容写到哪里;

3.从文件中读数据:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE*stream);
//第一个参数是读完要装进那哪;第二个参数是每次读出几个字节;
//第三个参数是读到的字符串的长度;第四个参数是要读的文件;

2.Linux下的文件相关系统调用接口

<1>. int open(const char *pathname, int flags);
//第一个参数表示要打开一个文件
//第二个参数的选项有:O_RDONLY 只读打开
////////////////////////////////////OWRONLY 只写打开
////////////////////////////////////O_RDWR 读、写打开(前三选项必须选且只能三选一)
////////////////////////////////////O_CREAT 若文件不存在,则创建
////////////////////////////////////O_APPEND 追加写

//头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

//返回值:成功则返回新打开的文件描述符,失败返回-1

<2>ssize_t write(int fd, const void *buf, size_t count);
//函数头文件为: #include<unistd.h>
//write()从缓冲区中写入字节数

<3> ssize_t read(int fd, void *buf, size_t count);
//函数头文件为: #include<unistd.h>
//read()函数读取文件中的字节数。
//描述符fd进入从buf开始的缓冲区。
//如果count为0,则read()返回0,没有其他值结果。如果计数大于SSIZE_MAX,则结果
是未指定的。

<4>int close(int fd);//关闭一个文件,参数为一个文件描述符
//函数头文件为: #include<unistd.h>

3.相关接口的简单使用实例

公共头文件:
这里写图片描述

向文件中写:
这里写图片描述

从文件中读:
这里写图片描述

测试结果:因为我向文件里写入了5次 “study every day\n”,所以也应该读出来5次,我把两个文件分别编译运行后,得出如下结果:
这里写图片描述

4.对比fd和FILE结构体

文件描述符fd:
      事实上,文件描述符就是一个从0开始的小整数。Linux进程默认情况下都有三个缺省的文件描述符,分别是标准输入0,标准输出1,标准错误2。0,1,2对应的物理设备一般是:键盘,显示器,显示器,所以输入输出的时候也可以采用直接把要写入(或输出)的东西写到0(或1)。
      当我们打开文件的时候,操作系统在内存中就要创造相应的数据结构来描述目标文件。于是就有了file结构体,表示一个已经打开的文件对象。而进程执行open系统调用,所以必须让进程和文件关联起来。每个进程都有一个指针*file,指向一张表files_struct,这张表的最重要的部分就是包含一个指针数组,每个元素都是指向一个打开文件的指针!所以,本质上,文件描述符就是该数组的下标,只要有文件描述符,就可以找到相应的文件。

这张照片是我在网上找的,虽然看上去很复杂,但是分析的很全面:
这里写图片描述



文件指针FILE定义说明文件指针的一般形式为:: FILE *指针变量标识符;       其中FILE应为大写,它实际上是由系统定义的一个结构,该结构中含有文件名、文件状态和文件当前位置等信息。在编写源程序时不必关心FILE结构的细节。       使用系统调用的时候用文件描述符的时候比较多,但是操作比较原始。C库函数在I/O上提供了一些方便的包装(比如格式化I/O、重定向),但是对细节的控制不够。如果过度依赖其中的一种只会徒增麻烦,所以知道两者的转换是很有必要的。FILE*是对fd的封装