基础IO
- 标准库I/O
- 系统调用I/O
- 认识文件描述符且理解重定向
- 文件系统基本认识
- 文件的软硬链接
⭐标准库I/O
- fopen :打开文件
- fclose:关闭文件
- fwrite:向文件写入数据
- fread:从文件读出数据
- fseek:跳转读写位置
函数原型:FILE *fopen(const char *path, const char *mode);
参数解释:
path:文件路径
mode:(打开方式)
- r:以只读方式打开文件;在起始位置读数据,文件不存在,则报错;
- r+:以可读可写方式打开;在起始位置读写数据;文件不存在,则报错;
- w:以只写方式打开文件;从起始位置写入数据;若存在该文件,则清空,若不存在,则创建;
- w+:以可读可写方式打开;从起始位置读写数据;若存在,则清空,若不存在,则创建;
- a:以追加只写方式打开;在文件末尾写数据;文件不存在,则创建;
- a+:以可读,写追加方式打开;读数据在起始位置,写从末尾开始;文件不存在,则创建。
返回值:
打开失败时,文件流指针返回NULL;成功时,返回文件流指针,做为操作文件的操作句柄.
int fclose(FILE *stream);
参数解释:
stream:文件流指针
补充:
feof()是检测流上的文件结束符的函数,如果文件结束,则返回非0值,否则返回0
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数解释:
ptr:是指向要被写入的元素数组的指针(要写入的内容)。
size:是要被写入的块的大小,以字节为单位。
nmemb:是块的个数
stream:表示是指向 FILE 对象的指针,该 FILE 对象指定了一个输出流(要写入的文件)。
返回值:
如果成功,则返回块的个数。失败或者到达文件末尾,则返回0
补充:
当块个数为1,写入的数据不足块的大小,返回值为0,为了防止这种情况,则可以将第二个参数写1,第三个参数写成一个数组的实际大小,则返回得是实际写入的字符串的长度。
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数解释:
ptr:用于接收数据的内存地址
size:要读的每个块的字节数,单位是字节
nmemb:块的个数
stream:这是指向 FILE 对象的指针,该 FILE 对象指定了一个输入流(要读出的文件)。返回值:
如果成功,则返回块的个数。失败或者到达文件末尾,则返回0
int fseek(FILE *stream, long offset, int whence);
参数解释:
stream:这是指向 FILE 对象的指针,该 FILE 对象标识了流。
offset:这是相对 whence 的偏移量,以字节为单位。
whence:3种情况
- SEEK_SET:从文件的起始位置偏移
- SEEK_CUR :从当前读写位置偏移
- SEEK_END:从文件末尾偏移作用:
该函数的作用:可以向后任意跳转文件的当前读写位置,即使文件没有数据也可以跳转读写位置
c++中的标准库的输入输出:
他们都是FILE*结构体(文件流指针)
标准输入 | 标准输出 | 标准错误 | |
---|---|---|---|
文件描述符 | 0 | 1 | 2 |
宏定义 | STDIN_FILENO | STDOUT_FILENO | STDERR_FILENO |
标准库IO接口的操作句柄是:FILE*------文件流指针
⭐系统调用I/O
- open:打开文件
- write:向文件中写入数据
- read:从文件中读取数据
- lseek:跳转文件中的读写位置
- close:关闭文件
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)
这是一个不定参函数,当第二个参数为O_CREAT,则必须给出文件的权限,也就是第三个参数(八进制)
参数解释:
pathname:文件路径名
mode :当使用O_CREAT的时候有可能新建文件,因此需要指定文件的权限
mode & (~umask) =实际最终得到的文件权限
flags:选项标志
必选选项(并且只能选择其一):
- O_RDONLY ----只读
- O_WRONLY----- 只写
- O_RDWR------可读可写
可选选项:
- O_CREAT:若文件不存在则创建。存在则打开
- O_EXCL :与O_CREAT一起使用,若文件存在则报错,单独是不起作用的
- O_APPEND:写入数据使用追加写方式
- O_TRUNC :打开文件的时候清空原有数据
例如:
w+:O_RDWR | O_CREAT |O_TRUNC
a: O_RDWR | O_APPEND | O_CREAT
返回值: 错误返回-1;成功返回一个非负整数—文件描述符—打开的文件的操作句柄
ssize_t write(int fd, const void *buf, size_t count);
参数解释:
fd:open返回的文件描述符—文件的操作句柄—通过这个fd指定要往哪个文件写入数据;
buf:要写入文件的数据的首地址;
count:要写入文件的数据长度;
返回值:成功返回实际写入文件的数据字节长度 失败返回:-1
sszie_t read(int fd,void *buf,szie_t count)
参数解释:
fd:open返回的文件描述符;
buf:一块缓冲区,从文件中读取的数据的放置位置,同时文件的当前读写位置向后移;count:想要读取的数据长度。
返回值:
(1)如果成功,返回读取的字节数;
(2)如果出错,返回-1并设置errno;
(3)如果在调read函数之前已是文件末尾,则返回0
off_t lseek(int fd,off_t offset,int whence)
参数解释:
fd:打开文件所返回的文件描述符;
offset:偏移量;
whence:偏移位置,从哪里开始偏移,有3种情况:
- SEEK_SET—文件起始位置
- SEEK_CUR—文件当前读写位置
- SEEK_END—文件末尾返回值:
返回值:成功时返回当前位置相对于起始位置的偏移量;失败时返回-1
int close(int fd):
作用:通过文件描述符关闭文件,释放资源
fd:文件描述符
返回值:成功返回0,失败时返回-1
⭐认识文件描述符且理解重定向
文件描述符
文件描述符:是一个非负整数,是操作文件的句柄。是内核中一个进程打开的文件描述信息表的下标–通过这个下标可以在内核中找到相应的文件描述信息,通过这个描述信息可以实现文件的操作。
文件描述符操作的原理(文件描述符有个分配规则:最小未使用)
为什么打开一个文件,如果不操作了一定要关闭,释放资源?
因为文件描述符实际是有限的,若不关闭文件,文件描述符用光,则在进程中就打不开新文件了.
一个程序运行起来,进程中会默认打开三个文件:
- 标准输入—0
- 标准输出—1
- 标准错误—2
重定向
概念:将数据不再写入原本的文件,而是写入新的指定的文件中—实现方式就是替换这个描述符对应的文件描述信息,使文件描述符指向新的文件描述信息。
原理:实际是描述符的重定向,改变描述符所指向的文件,就改变了数据的流向
实现该功能的函数:int dup2(int oldfd,int newfd)
功能:让newfd这个描述符也指向odlfd所指向的文件,这时oldfd和newfd都能够操作oldfd所指向的文件。
文件描述符与文件流指针的关系:
文件描述符:非负整数—系统调用的IO接口
文件流指针:FILE结构体—typedef struct _IO_FILE FILE—库函数IO接口的操作句柄
问题来了:为什么多此一举封装fd?
请感受系统调用接口和库函数的区别:
那么问题又来了:缓冲区在什么地方?
在文件流指针的结构体中定义了缓冲区,这个缓冲区通常被称为用户态缓冲区
⭐文件系统基本认识-软硬连接
文件系统:就是磁盘上管理文件的系统
以linux下的ext2文件系统为例:
文件的存储流程:
通过超级块找到inode位图/数据块位图,通过数据块位图快速找到空闲的磁盘块存储文件数据,通过inode位图快速找到空闲的inode节点存储文件的元信息;—文件数据存储完毕。
获取文件的数据流程:
通过文件名打开一个文件,在所在目录文件中通过文件名找到这个文件的inode节点号;在磁盘超级块中找到inode节点区域,根据inode节点号,快速找到inode节点,得到数据存储的磁盘块号,取出数据。
每一个文件都有一个唯一的inode节点 ;
ls -i:可以看到文件的inode节点号;
⭐文件的软硬链接
软链接 / 硬连接:可以通过软链接文件或者硬链接文件操作源文件
如何创建软链接文件以及硬链接文件:(源文件:test.txt)
为源文件创建一个硬链接文件:ln test.txt test.hard
为源文件创建一个软链接文件:ln -s test.txt test.soft
软链接文件与硬链接文件的区别:
- 本质区别:软链接文件是一个独立的文件,类似于文件的快捷方式,有自己的inode节点硬链接文件是一个文件的目录项,类似于一个文件的别名,与源文件指向相同的一个inode节点
- 操作方式的不同:软链接文件通过存储的源文件路径找到源文件inode,进而访问文件数据;硬链接文件直接通过自己的inode节点号直接访问文件数据
- 删除源文件:软链接失效,硬连接仅仅是链接数-1,依然可以访问
- 软链接可以跨分区建立,但是硬链接不可以
- 软链接可以对目录创建,但是硬链接不可以
OK,今天笔者先总结到这里。如有问题或者疑惑,欢迎各位小伙伴们指出。我们一起交流,一起进步!