简述
对文件进行操作,有文件IO和标准IO两种
标准IO: 采用库函数的方式对文件进行读写操作(对文件读写的函数接口出自于库)stdio.h
文件IO:采用系统调用的方式对文件进行读写操作(对文件的读写操作功能有内核提供) ,并且不带缓存,
系统调用:内核提供的一个接口层,用用程序通过此接口可以实现内核为应用程序提供的各种功能
系统调用的流程:
封装函数 -- 系统调用接口层(软中断)-- 系统调用的服务例程 -- 内核函数
一、标准I/O
标准IO是对文件IO的统合,类似于函数和命令的关系。而且每调用一次文件IO,处理器模式来回转换一次。
标准IO,将多次调用放到缓存区,到达一定程度在让处理器进行操作。
文件IO没有缓存区,标准IO有缓存区
系统调用发生三件事:
1)处理器状态发生改变 由用户态切换为内核态(提高处理器的执行级别)
2)系统调用的编号 每一个系统调用都会对应一个编号
3)实现参数传递 先将参数放入到CPU寄存器,在执行内核函数之前,将参数取出,放入到内核进程的堆栈区
1、简介
标准IO当对文件进行操作时,先操作缓存区,然后等待缓存区满足一定条件时,在进行真正的读写操作,减少系统的调用的次数,提高对文件操作的效率
对文件操作,操作描述文件属性的结构体(FILE)指针
char* _IO_buf_base; /* Start of reserve area. */ 缓冲区的开始处
char* _IO_buf_end; /* End of reserve area. */ 缓冲区的结尾处
标准IO(对文件读写的方式)
1)以字符的形式
2)以字符串的形式
3)以数据单元(二进制码)的形式
退出缓存区的三种方式
程序结束
缓存区填满
特定命令刷新,例如\n
标准IO中有三种类型的缓冲,下面会进行详细介绍
2、标准I/O的函数
2.1、 fopen
函数原型:FILE *fopen(const char *path, const char *mode);
功能:打开一个文件
参数:path 路径名(文件名)
mode r 以读的方式打开文件,如果文件不存在,报错(文件必须存在)
r+ 以读写的方式打开文件,如果文件不存在,报错(文件必须存在)
w 以写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将文件中的数据清空
w+ 以读写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将文件中的数据清空
a 以写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将数据写入到文件的末尾
a+ 以读写的方式打开文件,如果文件不存在,自动创建,如果文件存在,将数据写入到文件的末尾
返回值:成功 流指针(描述文件属性的结构体指针)
失败 NULL
2.2、 perror和strerror
函数原型:void perror(const char *s);
功能:打印系统错误消息(消息保存在错误码errno)
函数原型:char *strerror(int errnum);
功能:返回对错误码的描述
参数:errno
2.3、 fputc
函数原型:int fputc(int c, FILE *stream);
功能:向文件中写入一个字符
参数:c 写入到文件中的字符
stream 流指针(fopen函数的返回值)
返回值:成功 写入的字符
失败 EOF
2.4、 fgetc
函数原型: int fgetc(FILE *stream);
功能:从文件中读取一个字符
参数:stream 流指针(fopen函数的返回值)
返回值:成功 返回读取的字符
失败 EOF
2.5、 fputs
函数原型:int fputs(const char *s, FILE *stream);
功能:向文件中写入字符串
参数:s 写入文件中的字符串
stream 流指针
返回值:成功 非负数
失败 EOF
2.6、 fgets
函数原型: char *fgets(char *s, int size, FILE *stream);
功能:从文件中读取字符串
参数:s 读取的字符串保存的位置
size 设置读取的字节数
stream 流指针
返回值:成功 返回读取的字符串
失败 NULL
1)当文件中的数据字节数 >= size , 此时只能读取size-1个字符,最后一位自动补’\0‘,表示字符串到此读取结束
2)当文件中的数据字节数 < size , 此时将文件中的数据全部读出,在最后一位补’\0‘
文件:abcd
fgets: N = 4
读取结果:abc ’\0‘
fgets:N = 7
读取结果:abcd'\0'
1)当文件中的换行符’\n‘之前的数据字节数 >= size, 读取size-1个字符,最后一位自动补’\0‘
2)当文件中的换行符’\n‘之前的数据字节数 < size , 只能读取到'\n'之前所有的数据,fgets在'\n'补'\0',表示字符串到此读取结束
文件:abcd'\n'qwer'\n'
fgets: N = 128
读取结果:abcd'\n'\0'
2.7、 fclose
函数原型:int fclose(FILE *stream);
释放一个流指针。
函数退出后系统自动回收。
3、系统自定义的流指针
系统自定义的流指针(FILE *)--操作终端
标准I/O预定义3个流,他们可以自动地为进程所使用
stdin 标准输入 默认终端输入
stdout 标准输出 默认终端输出
stderr 标准出错输出 (报错)
函数原型:int fprintf(FILE *stream, const char *format, ...);
4、缓冲区
缓冲区的概念:
标准IO中有三种类型的缓冲:
1)全缓冲--当流与文件相关联的时候,此时操作的是全缓冲区
FILE *fp
刷新条件:程序正常退出
缓冲区写满
强制刷新 fflush();
大小:4096
2)行缓冲--当流与终端相关联的时候,此时操作的是行缓冲区
stdin stdout
刷新条件:程序正常退出
缓冲区写满
强制刷新 fflush();
换行符"\n"
大小:1024
3)不缓冲--没有缓冲区
stderr
大小:0
5、流的读写位置
5.1、 fseek
函数原型:int fseek(FILE *stream, long offset, int whence);
功能:定位流的读写位置
参数:stream 流指针
offset 偏移量 相对于第三个参数再次发生的偏移
whence SEEK_SET 定位到文件的开始处
SEEK_CUR 定位到文件的当前位置
SEEK_END 定位到文件的末尾处
fseek(fp, 0,SEEKSET);
返回值:成功 0
失败 -1
5.2、 ftell
函数原型:long ftell(FILE *stream);
功能:获取当前读写位置(获取当前读写位置相对于文件开始处的偏移量)
参数:stream
返回值:成功 当前的读写位置
失败 -1
6、以数据单元的形式对文件进行操作
数据单元的格式:字符、字符串、构造数据类型
6.1、 fwrite
函数原型:size_t fwrite(const void *ptr, size_t size, size_t nmemb,
FILE *stream);
功能:向文件中写入单元数据
参数:ptr 写入文件的数据单元
size 写入文件的数据单元的大小
nmemb 写入的数据单元的个数
stream 流指针
返回值: 成功 > 0
失败 < 0
6.2、 fread
函数原型: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件中读取数据单元
参数:ptr 从文件中读取的数据
size 读取的数据单元的大小
nmemb 读取的数据单元的个数
stream 流指针
返回值:成功 > 0
失败 < 0
注意:fwrite与fread函数都是对二进制码进行操作,所以如果写入的是数字,将会是一种类似于乱码的形式
二、文件IO
文件IO的本质:系统调用
文件I/O的特殊性:可以操作硬件
1、文件描述符
标准IO;操作核心--流指针
文件IO: 操作核心--文件描述符
文件描述符的特点:
1、 文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。
2、文件描述符本质上讲,就是一个值,通过文件描述符可以对文件进行操作,文件的标识通过inode号区分,不同的文件inode
3、当打开一个文件的时候,系统会自动生成三个文件描述符,分别是 0 1 2 ,分别对应的文件是标准输入文件,标准输出文件,标准出错文件
4、同一个进程,文件描述符的值最大不能超过1024
5、同一个进程,文件描述符不会出现重复
2、打开关闭文件函数
函数原型: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_EXCL 文件存在,报错
O_TRUNC 如果文件存在,将文件中的数据清空
r 对应 O_RDONLY 以只读的方式打开一个文件,如果文件不存在,报错
r+ 对应O_RDWR 以读写的方式打开一个文件,如果文件不存在,报错
w 对应O_WRONLY|O_CREAT|O_TRUNC; 以只写的方式打开一个文件,如果文件不存在,创建;如果文件存在,清空数据
w+ 对应 O_RDWR|O_CREAT|O_TRUNC;以读写的方式打开一个文件,如果文件不存在,创建;如果文件存在,清空数据
a 对应O_WRONLY|O_CREAT|O_APPEND;以只写的方式打开一个文件,如果文件不存在,创建;如果文件存在,写入到文件的末尾
a+ 对应O_RDWR|O_CREAT|O_APPEND;以读写的方式打开一个文件,如果文件不存在,创建;如果文件存在,写入到文件的末尾
O_WRONLY | O_RDONLY 不等于 O_RDWR :因为他们都是宏定义,实际上是八位二进制数
mode 指定该文件所属的用户对其执行权限 0666
如果第二个参数指定O_CREAT,必须有第三个参数 ;文件权限为(mode & ~umask). ; mode可以有两种方式书写,一种为八进制数字,一种为字符形式,详细可以使用man查看
umask的作用是自动屏蔽一些用户权限
返回值:成功 文件描述符
失败 -1
函数原型:int close(int fd);
关闭一个文件描述符
3、文件I/O的读写函数
3.1、写函数 write
函数原型: ssize_t write(int fd, const void *buf, size_t count);
功能:向文件中写入count个字节数据(不论数据格式,只论写入的字节数)
参数:fd 文件描述符
buf 写入文件的数据
count 需要写入的字节数
返回值:成功 实际写入的字节数
失败 -1
3.2、读函数 read
函数原型:ssize_t read(int fd, void *buf, size_t count);
功能:期望从文件中读取count个字节的数据
参数:fd 文件描述符
buf 读取的数据保存位置
count 期望读取的字节数
返回值:成功 实际读取的字节数
0 当前的读写位置在文件末尾处
失败 -1
文件IO 的读写方式的参数分配,第一个参数为文件位
第二个为数据位
第三个为数据字节数
4、文件描述符的读写位置
函数原型:off_t lseek(int fd, off_t offset, int whence);
功能:定位文件的读写位置
参数:fd 文件描述符
offset 相对于第三个参数偏移量
whence SEEK_SET 定位到文件的开始处
SEEK_CUR 定位到文件的当前读写位置
SEEK_END 定位到文件的末尾
返回值:成功 返回定位的位置相对于文件开始处的偏移量
失败 -1
不同于标准io的fseek函数,返回值为偏移量,而不是-1 or 0;
5、目录读取
1、获得目录函数接口:(目录的open函数)
函数原型: DIR *opendir(const char *name);
功能:打开一个目录,获得目录流指针
参数:name 目录名
返回值:成功 目录流指针
失败 NULL
2、读取目录(一个文件一个文件的读)
函数原型: struct dirent *readdir(DIR *dirp);
功能:读取目录,返回一个描述文件信息的结构体
参数:dirp 目录流指针
返回值:成功 struct dirent *
struct dirent {
char d_name[256] 文件名
}
失败 NULL
6、获取文件的属性信息
函数原型:int stat(const char *path, struct stat *buf);
功能:获取文件的属性信息,保存在第二参数中
参数:path 文件名
buf 保存文件属性的结构体
struct stat {
dev_t st_dev; /* ID of device containing file */ 设备号
ino_t st_ino; /* inode number */ 索引号
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */ 硬链接数
uid_t st_uid; /* user ID of owner */ 所属用户的ID 1000
gid_t st_gid; /* group ID of owner */ 组ID
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */ 文件的大小
time_t st_atime; /* time of last access */ 上一次进入文件的时间
time_t st_mtime; /* time of last modification */ 上一次修改文件的时间
time_t st_ctime; /* time of last status change */ 上一次文件状态改变的时间
};
返回值:成功 0
失败 -1
标准I/O和文件I/O的函数对应
扩展
相关内容请看UNIX系统编程手册上册,第五章