I/O的英文全拼就是 Input/Output,就是输入/输出的意思。I/O也叫I/O流,就是将数据比作水一样来回的流来流去。所以,通常说的“一个流”对于标准I/O来说就是一个文件描述符(fd)所代表的I/O,对于标准库I/O来说就是一个文件指针所代表的I/O。
对于文件I/O的三个标准操作步骤就是:
>1. 打开文件
>2. 操作文件内容
>3. 关闭文件
标准I/O和标准库I/O的区别就是: 标准库I/O是对标准I/O的进一步封装,也就是标准库I/O函数实际上调用了标准I/O中对应的函数,并且在调用的基础上添加了一个待处理缓冲区。待处理缓冲区的意思就是标准I/O将读入程序的数据先放入这块缓存,然后标准库I/O则根据需要在从这块缓存中取。比如 :getc(),getline()分别从缓存中以一次一字符和一次一行的形式取。而写入磁盘的方式正好与读入内存的顺序相反。
标准I/O函数及参数
打开文件
int fileno(FILE *fp);
// 将文件指针代表的I/O流得到用文件描述符代表的流
int open(const char *file_path, int flags, .../* mode_t mode */);
int openat(int fd, const char *file_path, int flags, .../* mode_t mode */);
以上两个函数的区别在于:open()是以绝对路径打开文件,而openat()可以以绝对路径打开,也可以用第一个参数fd提供的工作路径位为参考,以相对路径打开文件。
-
file_path:为文件路径不必多说。
-
flags:这个参数用很多常量来表示。下面看一下这些常量所表示的意义:
- O_RDONLY : 以只读的方式打开
- O_RDWRONLY : 以只写方式打开
- O_RDWR : 以读写方式打开
以后三个常量只能选择一个
下面说一些常用的常量可以选择多个或不选 - O_APPEND :在写的时候以追加的方式写入到文件末尾
- O_CREAT :如果文件不存在则创建文件,此常量使用的时候要指定函数的最后一个参数
- O_EXCL :如果文件存在则出错
- O_TRUNC :如果文件存在,且打开时有写的权限,则将文件长度截为0
-
mode:表示创建文件是赋予的权限,可以有常量表示,也可以用8进制数表示
操作文件
ssize_t read(int fd, void *buffer, size_t nbytes);
ssize_t write(int fd, void *buffer, size_t nbytes);
设置文件偏移量
off_t lseek(int fd, off_t offset, int whence);
关闭文件
void close(int fd);
标准库I/O函数及参数
打开文件
FILE * fopen(const char *file_path, const char *mode);
以权限为 mode 打开一个文件
FILE * fdopen(int fd, const char *mode);
以权限为 mode 打开一个已经用open()打开过的,fd指向的文件。这种方式是用于:在程序中创建的,非 **普通文件**类型但能用文件描述符表示的文件。比如:网络描述符 和 管道等。
FILE * freopen(const char *file_path, const char *mode, FILE *fp);
以权限为 mode 打开一个文件,并将该文件定向到指定文件指针。一般是 stdin,stdout,stderr
以上三个函数 :正确返回一个文件指针 FILE *, 错误返回 NULL
mode的类型有一下几种:
- “r” 或 “rb”:以只读方式打开
- “w”或“wb”: 以只写方式打开
- “a”或“ab”: 以只写、追加的方式打开或创建
- “r+” 或 “rb+”:以读、写方式打开
- “w+”或“wb+”: 以只读、写方式打开,且将文件长度变为0
- “a+”或“ab+”: 以只读、写、追加的方式打开或创建
操作文件
以一次一字符方式读
int getC(FILE *fp);
int fgetc(FILE *fp);
int getchar(void); //从标准输入中读取
以一次一字符方式写
int putc(FILE *fp);
int fputc(FILE *fp);
int putchar(void); //写入标准输入中
以二进制方式读写
size_t fread(void *buffer, size_t size, size_t bobj, FILE *fp);
size_t fwrite(void *buffer, size_t size, size_t bobj, FILE *fp);
操作文件偏移量
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
关闭文件
int fclose(FILE *fp);
操作缓冲区
刚开始的时候提到标准库I/O与标准I/O的区别就是封装了一个缓存,这块缓存同样可以操作
void setbuf(FILE *stream, char *buf);
将 buf 设置成 stream的缓冲区
void setbuffer(FILE *stream, char *buf, size_t size);
将buf 中 size 个sizeof(size_t)/sizeof(char)字节设置成stream的缓冲区
void setlinebuf(FILE *stream);
将 stream 设置成行缓冲
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
将buf 中 size 个sizeof(size_t)/sizeof(char)字节设置成stream的缓冲区,并且设置缓冲区的类型
setvbuf()的mode参数有一下几种情况:
_IONBF :unbuffered
_IOLBF: line buffered
_IOFBF :fully buffered
----摘自《UNIX环境高级编程(第三版)》