一、fopen、fwrite、fread
fopen
打开一个文件会返回FILE指针类型,打开文件有路径,然后再选择打开文件的方式若是以读的方式打开,那么不会创建,所有往文件中写入信息时会报错。但是若是以写的方式打开,在当前路径下寻找若是没有找到,则会创建。
打开文件方式
r:以读方式打开
w:以写方式打开
a:以追加方式打开
以写的方式打开,然后没有这个文件会创建这个文件
以w方式打开文件然后写入信息
fwrite向文件流中写入信息,man fwrite
在写入文件内容时,strlen不用+1,是因为fwrite读取的是文件内容,而加1读取字符\0是c语言规定,与文件读取无关,因此不用+1。写入时,fwrite是覆盖写入的,每次写入会将之前的清空然后再重新开始写入。
在一个程序中默认会打开三个流,stdin(标准输入流),stdout(标准输出流),stderr(标准错误流)。通常标准输入
为键盘,标准输出为显示器,标准错误也为显示器,而向显示器中写入时,标准错误和标准输出没有太大的区别。
二、open、write、read
文件是存储在磁盘上的,而磁盘是设备,那么当进程访问文件时,就是在访问硬件访问外设无论是访问什么文件都是在访问硬件,在计算机体系结构分层中,硬件处于最底层,然后用户在编写程序时,用户是无法直接访问硬件需要通过操作系统来访问硬件资源,用户要通过操作系统提供的接口来访问硬件上的文件,因此上层调用的c库函数底层调用由操作系统提供的系统接口。
open
第一个参数都是要先找到文件所在
第二个参数flags打开文件方式
flags: 打开文件时,可以传入多个参数选项,用下面的一个或者多个常量进行“或”运算,构成flags。
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR : 读,写打开
这三个常量,必须指定一个且只能指定一个
O_CREAT : 若文件不存在,则创建它。需要使用mode选项,来指明新文件的访问权限
O_APPEND: 追加写
flags为文件打开方式,一个文件可能会不止一种打开方式,可能是读方式打开或者写方式打开或者当文件不存在时还要创建文件或追加方式打开,也就决定了flags不仅仅是一个单纯整数,它是一个比特级别的标志位传递方式,以按位或传参实现不同的功能,以各种方式不同方式打开
传递不同参数时会实现不同的功能
以读写方式打开,使用系统提供的宏定义传参
只有两个参数的open接口没有对打开的文件设置权限,open第三个参数是对文件设置权限,就是拥有者所属组权限之类的。read
从文件中读取到缓冲区中
wrtie从文件缓冲区中读内容到指定文件中
三、文件描述符
open打开文件成功返回值为打开文件对应的文件描述符,若是打开文件失败则发挥-1.文件描述符就是整数编号,相当于是数组下标,而在计算机开机时,系统会给所有进程打开三个文件标准输入标准输出标准错误,然后它们会把0,1,2下标默认占去。
在文件关闭时,关闭的是文件描述符,就是指向的文件
从这里也可以证实0,1,2是键盘文件和显示器文件。
文件描述符是唯一标识一个文件的,在c语言中FILE是一个自定义类型结构体类型,其中有一个fileno,就是文件描述符编号
三个流对应文件描述符编号
操作系统为每个进程也提供了一个文件结构体,有各种属性集合其中有一个文件描述符的数组,里面存的是每个打开文件对象的指针,内存管理中为每个打开的文件管理一个文件对象,其中就有inode信息。
进程可以通过文件管理struct中的文件描述符表找到对应文件所在,操作系统对于打开的文件的属性放在一起,然后操作系统内描述一个被打开文件的信息,每一个文件被打开就要在内核创建一个file_struct对象其中包含直接或者间接属性,其中就有一个文件描述符表用于找到文件所在。而打开文件,默认从文件描述符表中最小下标没有被使用的开始使用。默认从最小开始,而对于一般进程,都是从3开始,因为0,1,2都被占用。
打开问件log.txt的文件描述符是3,而写的话就是直接向这个文件中写入。
当将显示器文件关闭之后,那么它所对应的文件描述符就没有指向就是相当于文件描述符表下标为1的文件中存储的显示器文件对象的地址清空然后后面再打开文件时就会把打开文件的对象地址填入文件描述符表中,然后文件描述符返回给用户。
此时再向显示器文件中写入时也不会被显示出来了,因为它的地址被覆盖了。就找不到显示器文件里,所有在显示器中打印的内容不会被显示出来!但是标准错误还是能打印出来的,一个文件可以被多个进程打开,在文件描述符表中,用不同数组下标存储同一个文件对象的地址,而当一个对象又多个文件描述符表指向时,不会因为一个文件描述符表关闭这个文件就关闭了,而是存在引用计数只有当引用计数减到0之后这个文件才是真正的被关闭了,就算是一个文件描述符表关闭也只是哪个进程对应要文件执行的内容关掉而其它进程还会执行。文件描述符的本质是数组下标
。在使用文件描述符时可以指定文件描述符,就算是这个文件描述符已有指向文件对象也可以将其覆盖然后转而指向自己文件对象,这一现象为文件重定向,将原本应该写到对应文件的内容写到指定文件。
就如将原本应该向显示器上显示的内容被写到了普通文件(log.txt)中,
在操作系统中有一接口dup2,它可以实现重定向的功能
oldfd:指定文件的fd
newfd:要覆盖文件的fd
newfd=oldfd
dup2之后将log.txt的地址填入1号文件描述符中,让1号成为新的,3号成为旧的
之后就将原本输出到显示器文件中的内容写到了log.txt中,而dup2之后不关闭,那么之后再打开的文件也是默认使用文件描述符用dup2接口把之后写入的文件描述符里的内容覆盖式写入到指定位置,就是增加一个引用计数。