UNP第五章 标准I/O库
2017-07-22 14:52
183 查看
流和FILE对象
在第三章中,所有I/O函数都是不带缓冲的。术语不带缓冲指的是每个read和write都调用内核中的一个系统调用。而对于标准I/O库,它们的操作是围绕流进行的:当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件关联。关于流的概念,个人理解流是对于数据特殊操作,例如在读数据操作时读一点处理一点;在写数据操作里生成一点, 写入一点。
A stream is a logical interface to a file.
流的定向(stream’s orientation)决定了所读、写的字符是单字节还是多字节的。若在未定向的流上使用一个多字节I/O函数,则该流的定向设置为宽定向的;若在未定向的流上使用一个单字节的I/O函数,则该流的定向设置为字节定向的。
#include <stdio.h> #include <wchar.h> int fwide(FILE *fp, int mode);
fwide函数可以设置未定向的流的定向,mode为负数,指定为字节定向;mode为正数,指定为宽定向;mode为0,fwide将不试图设置流的定向。注意,fwide并不改变已定向流的定向。
标准输入、标准输出和标准错误
这三个流可以自动地被进程使用,这三个标准I/O流通过预定义在头文件缓冲
标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数,因为这两个函数都需要应用程序自定义用户缓冲。标准I/O提供了以下三种类型的缓冲:
全缓冲:在填满标准I/O缓冲区后才进行实际的I/O操作。对于驻留在磁盘上的文件通常是由标准I/O库实施全缓冲的。
flush:冲洗缓冲区操作。flush说明标准I/O缓冲区的写操作:在标准I/O库方面,flush意味着将缓冲区的内容写到磁盘上(该缓冲区可能未写满);在终端驱动程序方面,flush表示丢弃已存储在缓冲区的数据。
行缓冲:在输入和输出中遇到换行符时,标准I/O库执行I/O操作。这允许我们一次输出一个字符,但只有在写了一行之后才进行实际操作。
对于行缓冲有两个限制:(1)因为标准I/O库用来收集每一行缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符,也进行I/O操作(这点类似全缓冲);(2)任何时候只要通过标准I/O库要求从a.一个不带缓冲的流或b.一个行缓冲的流中得到数据,那么就会冲洗所有行缓冲输出流。–》从一个不带缓冲的流中得到数据,即是说数据要从内核获得。
不带缓冲:标准I/O库不对字符进行缓冲存储。标准错误流stderr通常是不带缓冲的,这就使得错误信息可以尽快显示出来,而不管它们是否包含一个换行符。不带缓冲的情况下可以使得字符尽快得到输入或输出。
更改缓冲类型
#include <stdio.h> void setbuf(FILE *restrict fp, char *restrict buf); int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size); //成功返回0,出错返回非0
setbuf
setbuf可以用来打开或关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区(通常情况下指定之后该流为全缓冲的,但该流的关联文件如果是终端设备,那么某些系统也可以将其设置为行缓冲的);为了关闭缓冲,将buf设置为NULL。setvbuf
setvbuf可以精确地说明所需的缓冲类型,mode_IOFBF:FULL BUF全缓冲
_IOLBF:LINE BUF行缓冲
_IONBF:NONE BUF不缓冲
int fflush(FILE *fp);
此函数使该流所有未写的数据都被传送至内核;若fp为NULL,则此函数将导致所有输出流被冲洗。
打开流
#include <stdio.h> FILE *fopen(const char *restrict pathname, const char *restrict type); FILE *freopen(const char *restrict pathname, const char *restrict type, FILE *restrict fp); FILE *fdopen(int fd, const char *type);
fopen函数打开路径名为pathname的一个指定的文件
freopen函数在一个指定的流上打开一个指定的文件,若流已经打开,则先关闭流
fdopen函数取一个已有的文件描述符。此函数常用于创建管道和网络通信通道函数返回的描述符,因为这些特殊类型的文件不能用标准I/O函数fopen打开,我们必须先调用设备专用函数以获得一个文件描述符,然后用fdopen使一个标准I/O流与该描述符相结合
FILE *fp = fopen("/Users/hupac/Public/k.c", "rb"); //为打开文件关联一个流
读和写流
每次一个字符的I/O:int getc(FILE *fp); int fgetc(FILE *fp); int getchar(void); int k = getc(stdin); putc(k, stdout); //利用整型变量k来获取从fp指向文件中的一个字符,并用标准输出打印
getc和fgetc的区别在于,前者可以实现为宏,而后者不能实现为宏。宏函数作为预处理命令,调用函数所需的时间通常长于宏。
#define f(fp) getc(fp)
从流中读取数据后,可以调用ungetc将字符再压送回流中。但读入字符的顺序与压送回的顺序相反。
#include <stdio.h> int ungetc(int c, FILE *fp);
示例:往标准输入中压送一个字符
//测试ungetc(int, FILE) int in1 = getc(stdin); putchar(in1); int in2 = 4000 getc(stdin); putchar(in2); ungetc(in1, stdin); ungetc(in2, stdin); int out1 = getc(stdin); int out2 = getc(stdin); putchar(out1); putchar(out2);
结果:12回车
1221
分析:第一个ungetc把输入的1压入stdin,第二个ungetc把输入的2压入stdin,然后输出的顺序为2,1。从而得到结论压送回到流中的字符以后又可以从流中读出,但读出字符的顺序与压送回的顺序相反。
相关文章推荐
- APUE学习: 第五章, 标准I/O库
- 第五章 标准I/O库
- 第五章 标准I/O库
- 《APUE》笔记-第五章-标准I/O库
- apue学习第九天——标准I/O库(第五章)
- 《APUE》读书笔记—第五章标准I/O库
- 第五章 标准I/O库
- AUPE学习第五章------标准I/O库
- APUE读书笔记-第五章 标准I/O库
- UNP-UNIX网络编程 第五章:TCP客户/服务器程序示例
- APUE-第五章学习-标准I/O库-习题
- apue 第五章 标准i/o库
- 第五章 标准I/O库 课后练习题
- UNIX环境高级编程——第五章-标准I/O库
- UNP - 第五章 TCP客户/服务器示例 - 学习笔记
- 第五章 标准I/O库
- 第五章 标准I/O库
- 第五章 逃课(break和continue用法)
- [第五章]函数对变量的作用:局部变量和全局变量
- 第五章介质访问控制子层