文件IO
1.文件IO是基于系统调用
2.程序每进行一次系统调用,就会从用户空间向内核空间进行一次切换,执行效率较慢
3.目的:由于后期进程间通信,如管道、套接字通信,都使用的是文件IO,所以引入文件IO操作的概念
文件描述符
1.文件描述符本质上是一个非负整数,每个打开的文件,都会对应一个整数用于系统调用
2.每个程序打开文件的个数是有上限的,默认是1024个,可以通过ulimit -a进行查看
3.文件描述符使用原则:最小未分配原则
4.当使用open函数打开一个文件时,系统会给该文件分配一个文件描述符作为句柄
5.当一个程序运行时,默认会打开三个文件描述符,分别对应标准输入、标准输出、标准出错
open函数
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能:打开或可能创建一个文件
参数1:文件路径,是一个字符串表示要打开的文件
参数2:打开标识
三个必须选一个:O_RDONLY(只读)、O_WRONLY(只写)、O_RDWR(读写) 后面的可以以位或的方式连接,表示拥有该属性
O_CREAT:表示创建一个文件, 当第二个参数中有O_CREAT时,第三个参数必须要加上
O_APPEND:追加方式打开文件 O_TRUNC:清空文件内容
O_NONBLOCK:以非阻塞形式打开文件
O_EXCL:确保本次操作一定创建文件,如果文件已经存在,则open函数会报错,错误码为EEXIST
eg:
"w": O_WRONLY | O_CREAT | O_TRUNC
"r":O_RDONLY
"a":O_WRONLY | O_APPEND | O_CREAT
"w+":O_RDWR | O_CREAT | O_TRUNC
"r+":O_RDWR
"a+":O_RDWR | O_CREAT | O_APPEND
参数3:如果第二个参数中有O_CREAT,该参数必须设置,表示文件的权限,如果不设置,该文件的权限是一个随机权限
一般创建普通文件最大权限为:664
目录文件权限最大权限为:775
返回值:成功返回一个新的文件描述符,失败返回-1并置位错误码。
close函数
#include <unistd.h>
int close(int fd);
功能:关闭指定的文件描述符
参数:要关闭的文件描述符,关闭后,该文件描述符可以分配给其他文件使用
返回值:成功返回0,失败返回-1并置位错误码
write\read函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:将buf指向的地址中count个字节,写入到fd指向的文件中
参数1:文件描述符
参数2:容器起始地址,void*类型,表明可以写入任何类型的数据
参数3:要写入数据的个数
返回值:成功返回写入的字符个数,失败返回-1并置位错误码
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:从fd文件中,将count个字节读取到buf对应的容器中
参数1:文件描述符
参数2:容器起始地址,void*类型,表明可以读取任何类型的数据
参数3:要读取数据的个数
返回值:成功返回读取字节的个数,失败返回-1并置位错误码
光标移动(lseek)
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:移动光标位置
参数1:要移动光标的文件描述符
参数2:偏移量 >0:表示向后偏移 =0:表示不偏移 <0:表示向前偏移
参数3:偏移的起始位置
SEEK_SET:从文件开头偏移
SEEK_CUR:从文件光标当前位置偏移
SEEK_END:从文件末尾开始偏移
返回值:成功返回光标当前位置,失败返回(off_t)-1并置位错误码
lseek = fseek + ftell
关于文件描述符的拷贝问题
使用赋值的情况直接拷贝,多个文件描述符变量,共享同一个文件光标,通过一个文件描述符进行移动,所有的文件描述符的光标都会改变
int fd1 = -1;
if((fd1 = open("./test.txt", O_RDONLY)) == -1)
{
perror("open error"); return -1;
}
printf("fd1 = %d\n", fd1); //3
int fd2 = fd1; //对文件描述符直接进行拷贝
共享一个文件光标,因为描述符一样
使用dup函数,完成文件描述符的拷贝
#include <unistd.h>
int dup(int oldfd);
功能:通过旧的文件描述符,拷贝出一个新的文件描述符,新文件描述符遵循最小未分配原则
参数:旧文件描述符
返回值:新文件描述符,失败返回-1并置位错误码 执行后,新旧两个文件描述符都指向同一个打开的文件,共享文件光标位置
使用dup2函数完成两个文件描述符的拷贝
int dup2(int oldfd, int newfd);
功能:通过拷贝旧的文件描述符到新的文件描述符中
参数1:旧文件描述符
参数2:新文件描述符,如果newfd已经指向了某个已经打开的文件,则在进行拷贝之前,先将其关闭
返回值:成功返回新的文件描述符,失败返回-1并置位错误码
注意:newfd不是使用最小为分配原则,因为newfd在调用之前可能已经指向某个文件,调用后,无论是newfd函数oldfd都指向oldfd指向的文件通过该方式复制的文件描述符,依然共享同一个文件的光标
多次使用open函数完成对同一个文件的打开时,不同的文件描述符使用的是独立的光标
文件属性获取(stat)
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *statbuf);
功能:将给定的文件的相关属性,通过statbuf返回出来
参数1:要获取属性的文件路径是一个字符串
参数2:文件属性结构体指针,需要传递一个文件属性类型的结构体变量
返回值:成功返回0,失败返回-1并置位错误码
目录相关操作
opendir函数
#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);
功能:打开一个指定的目录,并返回该目录的目录指针
参数:要打开的目录,是一个字符串
返回值:成功返回目录指针,失败返回NULL并置位错误码
closedir函数
#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);
功能:关闭一个已经打开的目录指针
参数:目录指针
返回值:成功返回0,失败返回-1并置位错误码
readdir函数
#include <dirent.h>
struct dirent *readdir(DIR *dirp);
功能:读取指定目录中的下一个文件或目录的信息
参数:目录指针
返回值:成功返回当前文件或目录的信息,失败返回NULL并置位错误码
作业
1.标准io
2.文件io
3.stat函数
4.目录操作