一、文件IO的定义
文件IO由操作系统提供的基本函数,与操作系统是绑定起来的,也叫做系统调用
文件IO没有缓冲区
标准IO是通过文件流指针来维护一个文件,文件IO通过 文件描述符 来维护一个文件
1、文件描述符
文件描述符就是一个整数,实际上就是一个编号
2、打开文件的过程
尝试打开一个文件的时候,系统会主动给这个文件分配一个数组位置存储文件信息表,数组位置在内核中表示了一个文件,用这个位置编号来描述这个文件
在应用程序中通过编号(文件描述符)标识一个打开的文件
标准IO对文件IO的封装,在文件IO的基础上封装了一个缓冲区,同时将文件描述符也一起封装到FILE结构体中
文件描述符的范围是[0,1023],共1024个,文件描述符的总量也是上限,如果在不使用文件时需要关闭文件
文件描述符的分配原则:从小到大,依次遍历没有被占用的文件描述符
stdin-----0(stdin->fileno)
stdout---1(stdout->fileno)
stderr----2(stderr->fileno)
二、文件IO中常用的函数
open / close
read / write
lseek
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);
功能:打开一个文件
参数:
参数1:
const char *pathname:指定要打开的文件
参数2:
int flags:打开文件的方式与权限,flags的每一个二进制位表示一个权限
O_RDONLY:只读打开
O_WRONLY:只写打开
O_RDWR:读写打开
-----------------三选一
O_APPEND:追加方式打开
O_TRUNC:清空文件打开
O_CREAT:若文件不存在,则创建文件,必须带有第三个参数,创建的文件权限(读、写、执行)
参数3:
mode_t mode:在文件创建的时候,指定文件的权限,比如:0664,0444
当参数2没有包含 O_CREAT ,mode会被忽略
返回值:
成功,返回新(打开的文件)的文件描述符
失败,返回-1,设置errno
进行创建文件时,创建的权限不一定能够使用
在系统中只要创建文件都会 使用 umask(文件权限掩码),来进行控制
创建权限 & ~umask == 真实的权限
2.write函数
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
功能:将指定地址数据写入到文件中(按照字节写入--二进制形式)
参数:
参数1:
int fd:指定要写入的文件
参数2:
const void *buf:指定要写入数据的内存数据首地址
参数3:
size_t count:指定要写入文件的字节数
返回值:
成功,返回写入的字节数
失败,返回-1,设置errno
3.read函数
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
功能:从指定文件中读取数据
参数:
参数1:
int fd:指定从哪个文件中读取数据
参数2:
void *buf:指定读取的数据存储到哪个地址,可以是任意类型的数据地址
参数3:
size_t count:指定要读取的字节数
返回值:
成功:返回读取到的字节数 , 0读取到文件末尾,文件读取完毕
失败,返回-1,设置错误码errno
4.close函数
#include <unistd.h>
int close(int fd);
功能:关闭文件
参数:
参数1:
int fd:指定要关闭的文件(文件描述符)
返回值:
成功:返回0
失败:返回-1
5.lseek函数
#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
功能:修改文件偏移量(修改文件当前操作的位置)
参数:
参数1:
int fd:指定要修改哪个文件的偏移量
参数2:
off_t offset:偏移量大小,新的位置 , 需要根据whence基准 + offset进行偏移
如果想要往文件开头方向偏移,用负数表示
如果想要往文件结束方向偏移,用正数表示
参数3:
int whence:基准位置
SEEK_SET:文件开头位置
SEEK_CUR:文件当前位置
SEEK_END:文件结束位置
返回值:
成功,返回修改后距离文件开头位置的字节数偏移量
失败,返回-1,设置errno
注意:
使用fseek、lseek进行偏移时,若已经在文件开头,不能往前偏移;若在文件结尾,可以继续往后偏移。
在超过文件结束位置进行写操作时(在偏移之后的位置进行写数据),从原结束位置到新偏移位置之间没有数据,形成空洞文件,由系统自动对每个字节添加0
6.函数的使用
//使用文件IO读取数据
//open()函数的头文件
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
//其他文件IO的头文件
#include<unistd.h>
#include<errno.h>
#include<stdio.h>
int main(int argc, const char *argv[])
{
//实现数据输入文件
//打开文件,以读写方式打开,如果文件不存在,创建文件并清空,权限设置为0664
int fd;
fd=open("1.txt",O_RDWR|O_CREAT|O_TRUNC,0664);
//判断文件描述符,即打开文件函数的返回值是否小于0,小于则打开失败
if(fd<0)
{
perror("open:");//输出错误信息
return -1;
}
char buf[50]="while this is a append";//用数组存放打开文件的信息
write(fd,buf,50);//从程序当中的数组将数据写入到文件当中
char arr[100];
read(fd,arr,100);//从文件读取数据到程序
printf("%s\n",arr);
close(fd);//关闭文件
return 0;
}
三、总结
文件IO相对于标准IO而言要简单一些,但是其操作实现的功能都是打开文件,如果要做一个对比的话可以参考下表
fopen() mode 标准IO | open() flags 文件IO |
r | O_RDONLY |
r+ | O_RDWR |
w | O_WRONLY | O_CREAT|O_TRUNC , 0664 |
w+ | O_RDWR | O_CREAT|O_TRUNC , 0664 |
a | O_WRONLY | O_CREAT |O_APPEND , 0664 |
a+ | O_RDWR | O_CREAT |O_APPEND , 0664 |