1. 刷新缓冲区
#include <stdio.h>
int fflush(FILE *stream);
2. 打开一个流
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
2.1 fopen
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
FILE *fdopen(int fd, const char *mode);
FILE *freopen(const char *pathname, const char *mode, FILE *stream);
函数功能: 打开一个流。打开文件的权限为0666。
2.1.1 函数参数
(1)path : 路径名
(2)mode : 打开方式,有以下可选项
- r :只读方式。文件必须存在,否则报错。
- r+ :读写方式。文件必须存在,否则报错。
- w :只写方式。文件存在的话清空,不存在的话创建。
- w+ :读写方式。文件存在的话清空,不存在的话创建。
- a :以附加的方式打开(只写)。
- a+ :以附加方式打开(读写)。
2.1.2 函数返回值
- 成功:返回 指向FILE的结构体指针(流指针)
- 失败:返回 NULL
2.2 freopen
函数功能:重定向输入输出流。
2.2.1 函数参数
(1)pathname
重新定向的文件或者是路径
(2) type
文件打开的方式
(3) fp
被改变的流
2.2.2函数返回值
返回一个新的FILE指针。出错返回NULL。
举栗子:
freopen(“file1”, “w+”, stdout); 将stdout 重定向到 file1中。
freopen("/dev/tty", “w+”, stdout); 将stdout 重定向到 当前进程的控制终端中。
2.3 fdopen
2.3.1 函数功能及函数原型
FILE *fdopen(int fd, const char *mode);
将一个文件描述符和一个流结合。一般的fopen 函数只能操作普通文件,而如果想要使用标准IO操作设备文件,则需要使用这个函数。
一般使用场景:如果想用标准IO 操作设备文件,那么可以使用这个函数。即:使用标准IO 来操作设备文件。先获取设备文件的文件描述符,再使用标准IO操作。
2.3.2 函数参数
(1)fd
要操作设备的文件描述符。
(2)mode
与前面的mode一样
2.3.3 函数返回值
返回一个新的FILE指针。出错返回NULL。
3. 关闭一个流
3.1 fclose 函数
#include <stdio.h>
int fclose(FILE *stream);
功能:关闭一个已经打开的流。
注意:
- 关闭一个流之前,会刷下流的缓冲区中的数据,并释放缓冲区资源(也就是它底层调用了 free() 函数)。(因为缓冲区是malloc 来的。)
- 当一个进程终止,或者从main return 时,则所有未写缓冲区的流被刷新,所有打开的流都被关闭。
- 关闭一个流之后,不能再次关闭,否则结果是未知的(类似于两次 free)。
3.1.1 函数参数
要关闭流的指针。
3.1.2 函数返回值
- 关闭成功返回0
- 关闭错误返回EOF 并且设置错误码
4. 从一个流读一个字符
#include <stdio.h>
int getc(FILE *stream);
int fgetc(FILE *stream);
int getchar(void);
注意:
- getchar、getc 是通过宏实现的。fgetc是通过函数实现的。
- getchar() 等价于getc(stdin)
- getc() fgetc() 使用方法和效果是一样的,只是内部的实现细节不同。
4.1 函数参数
- c 输出字符的 ASCII 码
- stream 指定的流
4.2 函数返回值
- 读成功,获取读到字节的ASSII码
- 读失败,返回EOF,并设置error
5. 向一个流写一个字符
#include <stdio.h>
int putc(int c, FILE *stream);
int fputc(int c, FILE *stream);
int putchar(int c);
功能: 将指定的字符写入到指定的流中
注意:
- 从流中读取数据和向流中写数据三个函数一一对应。
- fput 的实现方式是函数。putc 和 putchar 的实现方式是宏。
- putc() fputc() 使用方法和效果是一样的,只是内部的实现细节不同。
5.1 函数参数
- c 输出字符的 ASCII 码
- stream 指定额流
5.2 函数返回值
- 写成功,获取读到字节的ASSII码
- 写失败,返回EOF,并设置error
5.3 区分EOF
5.3.1 区分EOF
读写一个流时,读写失败和到达文件末尾都会返回EOF,那么我们如何区别由于什么原因返回的EOF呢?
在FILE 结构体中,一般有两个标志字段,
- 出错标志
- 文件末尾标志
通过这两个标志,可以区别区别由于什么原因返回的EOF。
5.3.2 获取两种标志的函数
#include <stdio.h>
void clearerr(FILE *stream);
int feof(FILE *stream);
int ferror(FILE *stream);
5.3.2.1 函数描述
- feof : 用于检测文件末尾标志,如果该标志被设置返回非0的值,如果没有被设置返回0
- ferror :用于检测出错标志,如果该标志被设置返回非0的值,如果没有设置返回0
- clearerr :用于清除这两个标志
5.3.2.2用法:
while (!feof(fp) && !ferror(stdin)) {
cTemp = fgetc(fp);
}
解释: 如果没有达到文件末尾,以及没有出错的话,就继续读文件。也就是到达文件末尾以及出错了,都不能再继续读下去。
6. 从流中读一行
char *fgets(char *s, int size, FILE *stream);
char *gets(char *s);
推荐使用fgets。
6.1 函数参数
(1)s:
- 用于存储从制定流的缓冲区中获取的数据的首地址。 这里的缓冲区指的是应用程序的缓冲区,不要和流的缓冲区弄混了。数据会先存到流的缓冲区里,再从流的缓冲区中搬运到应用程序的缓冲区里。
(2)size:
- 缓冲区的长度
(3)stream:
- 指定的流
注意:
- 必须指定缓存的长度n。此函数一直读到下一个新行符为止,但是不超过n-1个字符,读入的字符被送入缓存。该缓存以null字符结尾。
- 如若该行,包括最后一个新行符的字符数超过n-1,则只返回一个不完整的行,而且缓存总是以null字符结尾。对fgets()的下一次调用会继续读该行。
- gets()并不将换行符存入缓存中, gets() 不把换行符加到新的缓冲区中。
- gets()不能从指定的流中获取数据,只能从标准输入流中获取数据。
比如:
- 通过fgets() 由标准输入读取数据,输入1234 然后敲回车,fgets() 函数会将1234和回车都存到缓冲区中。
- 通过gets() 由标准输入读取数据,输入1234 然后敲回车,gets() 函数只会将1234存到缓冲区中,而不会存回车。
6.2 函数返回值
- 读取成功:返回0
- 读取失败,或者到达文件末尾 返回NULL
7. 向流输出一行
int puts(const char *s);
int fputs(const char *s, FILE *stream);
puts函数功能:
向标准输出输出一行
fputs函数功能:
向指定的流里输出一行
函数fputs()将一个以null符终止的字符串写到指定的流,终止符null不写出。
注意
- 这并不一定是每次输出一行,因为它并不要求在null符之前一定是新换行符。
- puts()将一个以null符终止的字符串写到标准输出,终止符不写出。但是,puts()会自动将一个新换行符写到标准输出。
puts 和fputs 区别演示
#include <stdio.h>
int main()
{
char buf[] = {'a','b','c','d',' ','e','f'};
// fputs(buf,stdout);
puts(buf);
return 0;
}
可以看出:
- fputs 读到