IO(Input Output)
一、文件IO
1、open - 打开或创建一个文件
int open(const char *pathname, int flags, mode_t mode) ---->fcntl.h
参数:
1) char * 包含有文件名和路径
2) flags 打开文件的方式
3) mode 创建文件的权限
flag内容如下:
flag | 功能 |
---|---|
O_RDONLY | 只读 |
O_WRONLY | 只写 |
O_RDWR | 读写 |
O_CREAT | 创建一个文件 |
O_EXCL | 如果使用O_CREAT时文件存在,则可返回错误消息,这一参数可测试文件是否存在 |
O_TRUNC | 打开文件(会把已经存在的内容给删除) |
O_APPEND | 追加方式打开文件(不会把已经存在的内容给删除) |
返回值:
成功:文件描述符,它是一个非负的正整数,即文件的ID号。
出错:-1.
ID号的规律:从0开始累计,程序进行时(进程),内核会自动打开3个文件描述符。0,1,2分别对应标准输入,标准输出,标准出错。这样在程序中,每打开一个文件,文件描述符值从3开始累加。
Open函数创建文件时的权限与umask相关。
2、close - 关闭一个打开的文件
int close(int fd);
参数:
fd,文件描述符。
返回值:
成功返回0,出错返回-1并设置errno。
3、write - 从应用层往内核层写数据(输出)
ssize_t write(int fd, void *buf, size_t count);
参数:
fd,向哪个文件写;
void* ,向文件中写什么内容,通常是一个字符串,需要写入的字符串;
size_t,向文件中写多少个字节。
返回值:
实际写的字节数。
4、read - 从内核读(输入)
ssize_t read(int fd, void *buf, size_t count);
参数:
fd,文件描述符
void*,读到哪里去,为读出数据的缓冲区;
size_t,要读取的字节数;
返回值:
实际读取的字节数。
5、lseek - 调整读写的位置指针
off_t lseek(int fd, off_t offset, int whence);
参数:
1)fd,文件描述符;
2)off_t,偏移量,每一读写操作所需要移动的距离,可正负;
3)int,当前位置的基点,有三个标志。
SEEK_SET:当前位置为文件的开头,新位置为偏移量的大小。
SEEK_CUR:当前位置为文件指针的位置,新位置为当前位置加上偏移量;
SEEK_END:当前位置为文件的结尾,新位置为文件的大小加上偏移量的大小。
返回值:
成功:文件的当前位置;
出错:-1;
二、标准IO
文件IO与标准IO的区别:
文件IO:是直接调用内核提供的系统调用函数,头文件是:unistd.h;
标准IO:是间接调用系统调用函数,头文件是:stdio.h;
标准IO中的相关函数,不仅可以读写普通文件,也可以向标准输入(键盘)或标准输出(显示器)中读或写。
三个缓存的概念:
1、用户空间的缓存
我们程序中的缓存,就是你想从内核读写的缓存;
2、内核空间的缓存
每打开一个文件,内核在内核空间中都会开辟一块缓存;
3、库缓存
标准IO的库函数中的缓存。
1、fopen - 打开文件
FILE *fopen(const char *path, const char *mode); ------<stdio.h>
参数:
1)char*,文件路径;
2)char*,打开方式;
Mode:
b:二进制文件;
r:只读方式打开,文件必须存在;
w / a:只写方式打开,文件不存在则创建;w等价O_TRUNC,a等价O_APPEND;
+:读写方式打开,文件必须存在;
返回值:FILE*,文件流指针 类似于文件IO中的文件描述符
FILE定义:包含读写缓存的首地址、大小、位置指针等。 在/usr/include/libio.h.
权限:0666 & (~umask)
标准输入流:stdin;
标准输出流:stdout;
标准出错流:stderr。
2、fclose - 关闭文件
int fclose(FILE *stream);
参数:
FILE*,文件指针流;
返回值:
成功:0;
出错:EOF(-1);
在该文件 被关闭之前,刷新缓存中的数据。
行缓存(遇到新行符(\n)或写满缓存时,即调用系统调用函数)的读写函数:fgets,fputs;
无缓存(只要用户调用这个函数,就会将其内容写到内核中):stderr
全缓存(只有写满缓存才调用系统调用函数):fread,fwrite。
3、fgets - 读取数据
char *fgets(char *s, int size, FILE *stream);
参数:
1)char *,缓存,即读到哪去;
2)int,读多少个字节;
3)FILE *,从什么地方读。
返回值:
成功:返回缓存的地址;
NULL:已在文件尾端或出错。
4、fputs - 写入数据
char *fputs(const char *s, FILE *stream);
参数:
1)char *,缓存,即写什么内容;
2)FILE *,写到哪里去。
返回值:
成功:非负值;
出错:EOF(-1)。
5、fflush - 刷新缓存函数
fflush(FILE *fp);
把库函数中的缓存的内容强制写到内核中。
6、fseek - 调整读写位置指针函数
int fseek(FILE *stream, long offset, int fromwhere);
参数:(与文件IO中的lseek参数一致)
1)FILE *,文件指针流;
2)offset,偏移量;
3)int,基准。
返回值:
成功:0;
失败:-1;
void rewind(FILE *fp);用于设定流的文件位置指示为文件开始,
即rewind(fp) 等价于 fseek(fp, 0, SEEK_SET);
7、fgetc - 从文件中读取一个字符
int fgetc(FILE *fp);
参数:
文件流;
返回值:
成功:读取的字符;
EOF(-1):到文件结尾或出错;
8、fputc - 写一个字符到文件中
int fputc(int c, FILE *fp);
参数:
1)要写的字符;
2)文件流
返回值:
成功:返回输入的字符;
出错:EOF.
fgetc、fputc有缓存,但不是行缓存。
9、feof - 判断是否已经到文件结束
int feof(FILE *stream);
参数:
文件流;
返回值:
文件结束:非0;
没有:0;
10、ferror - 判断是否读写错误
int ferror(FILE *stream);
参数:
文件流;
返回值:
读写错误:非0;
不是:0;
11、clearerr - 清除流错误
void clearerr(FILE *stream);
参数:
文件流;
12、fread、fwrite - 全缓存的读写函数(全缓存)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
参数:
1)读到哪里去/写什么内容;
2)读/写的内容,每一个单元所占的字节数;
3)读/写的内容,有多少个单元数;
4)读/写到哪里去
总共字节数:size*nmemb。
返回值:
实际读写的字节数。
三、目录IO
包含头文件:#include <sys/types.h> 、#include <dirent.h>
1、mkdir - 创建目录
int mkdir(const char *path, mode_t mode);
参数:
1)创建的目论文件路径;
2)该目录的访问权限,与umask有关。
返回值:
成功:0;
失败:-1.
2、opendir - 打开目录
DIR *opendir(const char *pathname);
参数:
打开的目录及路径;
返回值:
成功:目录流指针;
出错:NULL。
3、closedir - 打开目录
int closdir(DIR *dr);
参数:
目录流指针;
返回值:
成功:0;
出错:-1。
4、readdir - 读取目录内容
目录里的子文件或子目录信息是以链表的形式存在,故需要读取全部信息,需要多次读取,直到返回值为NULL。
struct dirent *readdir(DIR *dr);
参数:
目录流指针;
返回值:
成功:struct dirent指针;
出错:NULL。
struct dirdent定义在头文件dirent.h中。
此结构体至少包含两个成员:
struct dirent
{
ino_t d_ino; //inode号
char d_name[NAME_MAX+1]; //文件名
}
5、seekdir/rewinddir - 调整目录流指针位置
void seekdir(DIR *dirp, long loc);
参数:
1)目录流指针
2)偏移量
void rewinddir(DIR *dirp); -->重置读取目录的位置为开头
参数:
目录流指针。