1.文件IO
文件IO是有操作系统提供的API接口,也可称之为系统调用。每一个操作系统的IO - API函数接口都是不一样的,这也造成linux下的可执行文件如果调用了文件IO的话,是不能够移植到其他平台的。
2.什么是文件描述符?
文件描述符是一个int类型的,非负的数据(数值比较小),是一个文件的标志。
当用户在用户空间使用open来打开一个文件时,内核空间会根据用户提供的名字去打开这个文件,并将文件信息封装到一个结构体中。在生成一个指向这个结构体的文件类型指针,随后将这个指针放进一个文件指针数组中并将数组下标返回给用户空间即用户获得到的文件描述符。
需要注意的是一个程序在刚运行的时候,内核会自动的为他打开3个设备文件并返回3个文件描述符。
标准输入 ---- 0
标准输出 ---- 1
标准错误输出 ---- 2
3.linux的文件IO接口
1.open
2.read
3.write
4.close
5.lseek
4.API接口使用
1.open
头文件:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
原型:
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
功能: 打开一个文件
参数:
pathname :路径及名称
flags :打开文件的方式
必须包括:
O_RDONLY:只读权限打开文件
O_WRONLY:只写权限打开文件
O_RDWR :读写权限打开文件
附加参数:(以或的形式去附加的)
O_APPEND :以追加写的方式打开文件
O_CREAT :如果文件存在则打开文件,如果文件不存在则创建文件,如果使用了O_CREAT
这个参数,需要使用open的第三个参数,给与权限是一个8进制的整型。例如:0664
O_EXCL : 如果文件存在则报错返回
O_NONBLOCK :以非阻塞方式打开一个文件
O_TRUNC :以清空的方式打开文件
返回值:
成功返回一个文件描述符
失败返回‐1
需要注意的是,如果使用0x666创建文件为什么出来的权限可能并不是0x666,因为操作系统有一个叫做文件掩码的机制,将其他用户权限的可写权限抹掉,可以使用umask查看文件掩码,或者使用 umask + 想要修改的权限值来修改文件掩码的值。
2.read
头文件:#include <unistd.h>
原型:ssize_t read(int fd, void *buf, size_t count);
参数:
fd :目标文件描述符
buf :存放读到的数据
count:读多少个(字节大小)
返回值:
成功:返回读到的字节个数
失败:‐1
读到文件末尾返回0
需要注意的是当最后一次read时如果文件剩余字节不够需要的字节数时,读到文件末尾时便返回已经读到的字节个数,再一次读取时返回0。
3.write
头文件:#include <unistd.h>
原型:ssize_t write(int fd,const void *buf,size_t count);
参数:
fd:目标文件描述符
buf:要写入的数据的地址
count:写入数据的大小(以字节为单位)
返回值:
成功:写入的字节个数
失败:-1
4.close
头文件:#include <unistd.h>
原型: int close(int fd)
参数:
fd:要关闭的文件描述符
返回值:
成功返回0
失败返回-1
5.lseek
头文件:
#include <sys/types.h>
#include <unistd.h>
原型: off_t lseek(int fd, off_t offset, int whence);
功能:操作读写指针,对读写指针进行偏移
参数:
fd :目标文件描述符 :‐‐‐‐》对哪个文件操作
offset:如何偏移,偏移多少
如果该数为负数,代表这向前进行偏移,如果偏移出了文件的开头,会报错返回
如果该数为正数,代表这向后进行偏移,如果偏移出了文件的末尾,会扩大文件,用'\0'来做填充。那么此类的文件被称为 ‐‐空洞文件‐‐
注意:如果偏移后没有对其进行任何写入操作,内核认为该偏移无效,
不会扩大文件大小。
whence:基准位置‐‐‐‐‐根据哪一个位置进行偏移
SEEK_SET:根据文件开头进行偏移
SEEK_CUR:根据用户当前位置进行偏移
SEEK_END:根据文件末尾进行偏移
返回值:
成功: 返回偏移的字节个数(根据文件开头来定)
失败: (off_t)‐1
6.实例
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
int main()
{
char buf_write[128] = {"hello world"};
char buf_read[128] = {0};
int fd = open("./1.txt",O_RDWR|O_CREAT,0x666);
//以读写的权限打开当前目录下的1.txt文件,不存在则创建一个权限为666的1.txt文件打开
if(-1 == fd)
{
perror("open");
return -1;
}
if(-1 == write(fd,buf_write,128))
{
perror("write");
return -1;
}
if(-1 == read(fd,buf_read,128))
{
perror("read");
return -1;
}
return 0;
}