为什么要学习IO
目的:为了将数据存储以及对于文件的操作
文件:普通文件或者硬件设备(Linux下一切皆文件)
Linux下的7种文件属性:
1.普通文件 -
2.目录文件 d
3.符号链接文件(软链接) l
4.字符设备文件 c
5.块设备文件 b
6.管道文件 p
7.套接字文件 s
IO的分类
第一类:标准IO(高级磁盘IO)
第二类:文件IO(低级磁盘IO)
标准IO与文件IO的区别
标准IO:
1.ANSI(美国标准协会)联合ISO(国际化标准组织)所形成的一个C标准(属于C库,含有一系列输入输出函数),只要操作系统支持C库,就可以使用这一类标准IO提供的函数,可移植性较高
2.操作的文件一般是普通文件
3.属于高级磁盘IO,存在缓冲区,减少了用户态切换至内核态,最后又返回用户态这样的频繁操作,意味着减少了系统开销
4.通过文件流(FILE*)操作文件(打开文件时,系统会自动将该文件的信息定义结构体类型struct FILE 来进行存储,因此可以通过FILE *文件指针来操作文件)
文件IO:
1.POSIX(可移植操作系统接口)推出的对于支持POSIX标准的系统间可以操作文件的一系列函数,UNIX系统一般都会支持POSIX的标准,可移植性不高(只能应用于UNIX系统)
2.操作的文件可以是普通文件或者设备文件(硬件)
3.低级磁盘IO,没有缓冲区,每一次都是系统调用,都会存在用户空间和内核空间的频繁切换工作,好处就是可以直接对于设备进行读写操作
4.通过文件描述符(非负的数字)来操作文件
系统调用和缓冲机制
库函数和系统调用函数的关系:大多数库函数都是由系统调用函数封装起来的
标准IO
流
概念:文件被打开时,创建的结构体名为FILE的结构体指针,形象的成为“流”
分析:为啥称结构体指针为流?
–》因为标准IO存在缓冲区,所以每一次向缓冲区不断放入数据(每一次的放入数据:均是需要通过文件指针来进行读写指向的文件),存在三个特点:
1.有源头:APP
2.有目的:缓冲区
3.持续性:不断放入数据到缓冲区
–》一旦具备以上3个特点,就会形成流,所以通过文件指针操作文件可以理解为是通过操作流来操作文件
流的分类
文件被打开的时候,会默认具备3个流:
标准输入stdin–>0 对应键盘
标准输出stdout–>1 对应终端
标准出错stderr–>2 向终端打印,不带缓冲区(意味着每一次出错就会立即刷新缓冲区)
因此:当用户以后想要操作文件时,就需要先打开文件,此时会拥有一个文件流指针,以后通过该文件指针就可以操作文件。
缓冲机制
全缓冲
理解:缓冲区被放满,程序结束,强制刷新,会引起缓冲区的刷新
行缓冲
理解:缓冲区被放满,程序结束,强制刷新,遇到换行符,会引起缓冲区的刷新
不带缓冲
理解:不存在缓冲区的概念–》每一次读写都是直接输出:stderr
名词解释:
缓冲区被放满:
程序结束:
强制刷新:
操作文件
提供给用户来操作文件的方式有3种:
思考:不管是那种方式来操作文件,流程为:
打开文件
函数原型:FILE *fopen(const char *pathname, const char *mode);
参数1:需要打开文件的名字(可以包含路径,指针类型)
参数2:打开文件的方式(指针类型)
返回值:
打开文件成功之后的文件流指针
失败为NULL
代码如下:
注意:进行写操作时,若指定文件不存在,会自动创建新文件,但读操作不会
操作文件–》读写文件
3种方法。
关闭文件
因此打开文件和关闭文件在标准IO下都是使用同一个接口,只是在操作文件的方式上存在选择。
按照字符操作
函数名:fgetc fputc
头文件:#include<stdio.h>
函数原型:int fgetc(FILE *stream);
功能:从指定的文件流中获取
参数:指定获取一个字符所处文件的文件流
返回值:
成功返回获取到的字符值,
读取到文件末尾返回EOF(-1),
操作中失败返回负数(不包含-1)
函数原型:int fputc(int c,FIFE *stream);
功能:向指定的文件流中输出一个字符
参数:
参数1:需要输出的指定字符(字符被称为单字节的整形)
参数2:指定输出字符到的文件对应的文件流
返回值:
成功返回刚写入的字符值
失败返回EOF(-1)
案例1:实现对于指定一个文件读取,读取方式为按照字符操作,将读取完毕之后的结果显示在终端行。(自己实现命令cat文件名)
思路:
1.打开需要显示文件内容所在的文件
2.获取一个字符
3.输出一个字符
4.重复2.3直至文件末尾截止
5.关闭文件
代码如下:
按照行操作
标志:寻找’\n’
函数:fgets fputs
函数原型:char * fgets(char *s, int size, FILE *stream);
参数1:即将存储内存空间首地址
参数2:存储内容空间的大小(可以sizeof()测得)
参数3:指定的文件流
返回值:
成功返回存储内容空间首地址
失败返回NULL
思考:fgets什么时候会返回?
—>情况1:第一次遇到’\n’就会返回
情况2:该行会比较长,需要多次读取才能读完,所以位于读到’\n’之前的多次都是读取到size-1就返回。
案例–>实现wc -l测试问文件行数的功能
按照块操作
函数:fread fwrite
函数原型:size_t fread(void ptr,size_t size,size_t nmemb,FILE *stream)
参数1:存储读取一块内容之后的空间地址
参数2:块的大小-->建议给1
参数3:块的个数-->建议给sizeof()
参数4:要读取的文件对应的文件流
返回值:成功代表读取的块的个数,失败返回0
函数原型:size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);
参数1:需要写入的内容之后的空间地址
参数2:块的大小-->建议给1
参数3:块的个数-->建议给sizeof()
参数4:要写入的文件对应的文件流
返回值:成功代表写入的块的个数,失败返回0
案例:
保存学生信息:
读取学生信息到结构体空间:
文件流的定位:
理解:文件指针的指示位置
代码如下:
特性函数:
1.perror("string");
作用:可以输出出错的原因
2.feof(FILE *stream);
作用:判断文件是否抵达文件末尾(不管是文本文件还是二进制文件,都可以判断)
返回值:
抵达文件末尾,返回值为非零
未抵达文件末尾,返回值为零
文件IO
操作文件IO的函数:
open close read write
打开文件
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
函数原型:
int open(const char *pathname, int flags);
功能:打开指定的文件
参数:
参数1:所需打开文件的名字(包含路径)
参数2:打开文件的方式-->主标志 | 副标志
返回值:
成功返回一个大于0的数字(文件描述符)
失败返回-1(errno ie set..)
int open(const char *pathname, int flags, mode_t mode);
功能:打开指定的文件
参数:
参数1:所需打开文件的名字(包含路径)
参数2:所需打开文件的名字(包含路径)
参数3:打开文件的方式-->主标志 | 副标志
返回值:
成功返回一个大于0的数字(文件描述符)
失败返回-1(errno ie set...)
关闭文件
#include <unistd.h>
int close(int fd);
功能:关闭一个文件描述符
参数:打开文件成功之后的文件描述符
写文件
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:向指定的文件描述符的文件内写入内容
参数:
参数1:打开文件之后的文件描述符
参数2:所需写入的内容所在空间首地址
参数3:需要写入的字节数
返回值:
成功返回写入的字节数
返回0代表没有写入任何内容
返回-1代表出错(errno is set...)
读文件
#include <unistd.h>
ssize_t read(int fd, const void *buf, size_t count);
功能:从指定的文件描述符的文件内读取内容
参数:
参数1:打开文件之后的文件描述符
参数2:存储读取到结果的空间首地址
参数3:可以读取的字节数-->sizeof测得
返回值:
成功返回存储的字节数
返回0代表读取完毕
返回-1代表出错(errno is set...)
案例:对于同一个文件进行读写操作的代码如下 :
代码如下:
建议选用while循环~
文件IO中文件指示位置定位
空洞文件
代码如下:
操作目录
函数:opendir readdir closedir
打开目录
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
操作目录
关闭目录
测试文件属性
穿透函数:当测试的文件是软链接文件时,此时测得属性是属于软链接所指向的源文件的属性
非穿透函数:当测试的文件是软链接文件时,此时测得属性是软链接文件自身的属性。
制作静态库和动态库
什么是库?
库存在的意义?
静态库
理解:
如何创建静态库
动态库
理解:
如何创建动态库