**

一、文件的编程

**:
文件编程的内容很多,但是重点在应用,主要关心如何用代码操作文件,实现文件创建,打开,编辑等自动化执行。
在这里插入图片描述

二、对文件使用的API

打开 open
读写 write/read;
光标定位 lseek;
关闭 close

三、API的使用

1、open函数的使用:在这里插入图片描述
参数说明:
1.pathname
要打开或创建的目标文件(路径)
2.flags
打开文件时,可以传入多个参数选项,用下面的
一个或者多个常量进行“或”运算,构成falgs
参数:
O_RDONLY: 只读打开
O_WRONLY: 只写打开
O_RDWR: 读,写打开
这三个常量,必须制定一个且只能指定一个
O_CREAT: 若文件不存在,则创建它,需要使
3.mode选项:来指明新文件的访问权限
O_APPEND: 追加写,如果文件已经有内容,这次打开文件所写的数据附加到文件的末尾而不覆盖原来的内容
ps:open函数具体使用那个,和具体应用场景相关,如目标文件存在,使用两个参数的open,如果目标文件不存在,需要open创建,则第三个参数表示创建文件的默认权限
权限:
1、可读:r 4
2、可写:w 2
3、执行:x 0
返回值
成功:新打开的文件描述符
失败:-1
open返回的文件描述符一定是最小的而且没有被使用的

2、close函数的使用:

int close(int fd)
参数说明:
fd:是需要关闭的文件描述符

3、write()函数写入操作

头文件:#include<unistd.h>
原型:
ssize_t write(int fd,const void*buf,size_t count);
参数说明:
fd:是文件描述符(write所对应的是写,即就是1)
buf:通常是一个字符串,需要写入的字符串
count:是每次写入的字节数(也就是buf的大小)
返回值:
成功:返回写入的字节数
失败:返回-1并设置errno
ps: 写常规文件时,write的返回值通常等于请求写的字节数count, 而向终端设备或者网络写时则不一定

4、read()读文件操作

头文件:#include<unistd.h>
功能:用于从文件描述符对应的文件读取数据(从打开的设备或文件中读取数据)

原型:
ssize_t read(int fd,void *buf,size_t count)
参数说明:
fd: 是文件描述符
buf: 为读出数据的缓冲区;
count: 为每次读取的字节数(是请求读取的字节数,读上来的数据保存在缓冲区buf中,同时文件的当前读写位置向后移)
返回值:
成功:返回读出的字节数
失败:返回-1,并设置errno,如果在调用read之前到达文件末尾,则这次read返回0

5、lseek函数 用法 :

表头文件:#include
#include
定义函数:off_t lseek(int fildes, off_t offset, int whence)
  函数说明:每一个已打开的文件都有一个读写位置,当打开文件时通常其读写位置是指向文件开头,若是以附加的方式打开文件(如O_APPEND),则会读写位置会指向文件尾。当read()或write()时,读写位置会随之增加,lseek()便是用来控制该文件的读写位置。参数fildes为已打开的文件描述词,参数offset为根据参数whence来移动读写位置的位移数。参数whence为下列其中一种:
SEEK_SET 参数offset即为新的读写位置
SEEK_CUR 当前读写位置后增加offset个位移量。
SEEK_END 将读写位置指向文件尾后再增加offset个位移量
当whence值为SEEK_CUR或SEEK_END时,参数offset允许负值的出现
下列是较特别的使用方式:
  1)欲将读写位置移到文件开头时:lseek(int fildes, 0, SEEK_SET)
  2)欲将读写位置移到文件尾时时:lseek(int fildes, 0, SEEK_END)
  3)欲将取得目前文件位置时:lseek(int fildes, 0, SEEK_CUR)
  返回值:当调用成功时则返回目前的读写位置,也就是距离文件开头多少个字符。若有错误则返回-1, errno会存放错误代码。
错误代码:EINTR 此调用被信号所中断
6、文件的创建:
在这里插入图片描述

7、文件描述符

1、对于内核而言,所有打开文件都是由文件描述符引用的。文件描述符是一个非负整数。当打开一个现存文件或者创建新文件时,内核向进程返回一个文件描述符。当读一个文件时,用open或create返回的文件描述符标识该文件,将其作为参数传递给read和write。按照惯例,Unix shell使用文件描述符0与进程的标准输入相结合,文件描述符1与标准输出相结合,文件描述符1与标准输出相结合,文件描述符2与标准错误输出相结合,再打开一个新的文件的话,它的文件描述符就是3。STDIN_FILNO,STOUT_FILENO、STDERR_FILENO这几个宏代替了0、1、2这几个数字。
2、文件描述符,这个数字在一个进程中表示一个特定含义,当我们open一个文件时,操作系统在内存中构建了一些数据结构来表示这个动态文件,然后返回给应用程序一个数字作为文件描述符,这个数字就和我们内存中维护的这个动态文件的这些数据结构定上了,以后我们应用程序如果要操作这个动态文件,只需要用这个文件描述符区分。
3、文件描述符的作用域就是当前进程,出了这个进程文件描述符就无意义了。
4、在Linux中要操作一个文件,一般是先打开一个文件,得到文件描述符,然后对文件进行读写操作(或其他操作),最后是close关闭文件。
5、强调一点:我们对文件进行操作时,一定要先打开文件,打开成功之后才能操作,如果失败,就不用进行后边的操作了,最后读写完成后,一定要关闭文件,否则会造成文件损坏。
6、文件平时时存放在块设备中的,我们把这种文件叫静态文件,当我们去open打开一个文件时,Linux内核做的操作包括:内核在进程中建立一个打开文件的数据结构,记录下我们打开的这个文件;内核在内存中申请一段内存,并且将静态文件的内容从设备中读取到内核中特定地址管理存放(叫动态文件)。
7、打开文件以后,以后对这个文件的读写操作,都是针对内存中的一份动态文件,并不是针对静态文件。当然我们对动态文件进行读写以后,此时内存中的动态文件和块状设备中的静态文件就不同步了,当我们close关闭动态文件时,close内部内核将内存中的动态文件的内容去更新(同步)块设备中的静态文件。
8、为什么这么设计,不直接对块设备直接操作。
块设备本身读写非常不灵活,是按块读写的,而内存是按字节单位操作的,而且可以随机操作,很灵活。

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐