UNIX环境高级编程——第五章-标准I/O库

5.2 流和FILE对象

1、第三章的I/O函数都是围绕文件描述符的。即返回一个文件描述符,然后该文件描述符就用于后续的I/O操作。
对于标准I/O库,他们的操作是围绕流(stream)进行的。当用标准I/O库打开或创建一个文件时,我们已使一个流与一个文件相关联。

2、对于ASCII字符集,一个字符用一个字节表示。对于国际字符集,一个字符可用多个字节表示。
(1)标准I/O文件流可用于单字节或多字节(”宽”)字符集。
(2)流的定向决定了所读、写的字符是单字节还是多字节的。
(3)当一个流被创建时,它并没有定向。
(4)若在未定向的流上使用一个多字节I/O函数,则将该流的定向设置为宽定向的。
(5)若在未定向的流上使用一个单字节I/O函数,则将流的定向设置为字节定向的。

3、fwide函数可用于设置流的定向

#include <stdio.h>
#include <wchar.h>
int fwide(FILE *fp, int mode);
                        返回值:若流是宽定向的,返回正值;若流是字节定向的,返回负值;若流是未定向的,返回0

根据mode参数的不同值,fwide函数执行不同的工作:
(1)如若mode参数值为负,fwide将试图使指定的流是字节定向的
(2)如若mode参数值为正,fwide将试图使指定的流是宽定向的
(3)如若mode参数值为0,fwide将不试图设置流的定向,但返回标识该流定向的值
注意,fwide并不改变已定向流的定向

4、FILE结构包含了标准I/O库为管理该流的所有信息,包括:
(1)用于实际I/O的文件描述符
(2)指向用于该流缓冲区的指针
(3)缓冲区的长度
(4)当前缓冲区中的字符数以及出错标志等

5.3 标准输入、标准输出和标准错误

1、对一个进程预定义了3个流,并且这3个流可以自动地被进程使用,它们是:标准输入、标准输出和标准错误

5.4 缓冲

1、标准I/O库提供缓冲的目的是尽可能减少使用read和write调用的次数。

2、标准I/O提供了以下3种类型的缓冲:
(1)全缓冲。在这种情况下,在填满标准I/O缓冲区后才进行实际I/O操作。
(2)行缓冲。在这种情况下,当在输入和输出遇到换行符时,标准I/O库执行I/O操作。
(3)不带缓冲。标准I/O库不对字符进行缓冲存储。

3、术语冲洗(flush)说明标准I/O缓冲区的写操作
在UNIX环境中,flush由两种意思
(1)在标准I/O库方面,flush(冲洗)意味着将缓冲区中的内容写到磁盘上(该缓冲区可能只是部分填满的)
(2)在终端驱动程序方面,flush(刷清)表示丢弃已存储在缓冲区中的数据。

4、对于行缓冲有两个限制:
(1)因为标准I/O库用来收集每一行的缓冲区的长度是固定的,所以只要填满了缓冲区,那么即使还没有写一个换行符,也进行I/O操作。
(2)任何时候只要通过标准I/O库要求从(a)一个不带缓冲的流,或者(b)一个行缓冲的流(它从内核请求需要数据)得到输入数据,那么就会冲洗所有行缓冲输入流。

5、标准错误流stderr通常是不带缓冲的

6、ISO要求下列缓冲特征:
(1)当且仅当标准输入和标准输出并不指向交互式设备时,它们才是全缓冲的。
(2)标准错误决不会是全缓冲的。

7、很多系统默认使用下列类型的缓冲:
(1)标准错误是不带缓冲的
(2)若是指向终端设备的流,则是行缓冲的,否则是全缓冲的

8、对一个给定的流,可以调用下列两个函数更改缓冲类型

#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
int servbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);
                                            返回值:若成功,返回0,若出错,返回非0

(1)使用setbuf函数打开或关闭缓冲机制。为了带缓冲进行I/O,参数buf必须指向一个长度为BUFSIZ的缓冲区。(常量定义在

_IOFBF              全缓冲
_IOLBF              行缓冲
_IONBF              不带缓冲

下面列出这两个函数的动作,以及它们的各个选项。

如果指定一个不带缓冲的流,则忽略buf和size参数。
如果指定全缓冲或行缓冲,则buf和size可选择地指定一个缓冲区及其长度。
如果该流是带缓冲的,而buf是NULL,则标准I/O库将自动地为该流分配适当长度的缓冲区。
适当长度指的是由常量BUFSIZ所指定的值。

这里写图片描述

9、如果在一个函数内分配一个自动变量类的标准I/O缓冲区,则从该函数返回之前,必须关闭该流。

10、某些实现讲缓冲区的一部分存放它自己的管理操作信息,所以可以存放在缓冲区中的实际字节数少于size。

11、在任何时候,我们都可以强制冲洗一个流。

#include <stdio.h>
int fflush(FILE *fp);
                                    返回值:若成功,返回0;若出错,返回EOF。

此函数使该流所有未写的数据都被传送至内核,作为一种特殊情形,如若fp是NULL,则此函数将导致所有输出流被冲洗

5.5 打开流

1、下列3个函数打开一个标准I/O流

#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 *restrict type);
                                        3个函数的返回值:若成功,返回文件指针;若出错,返回NULL。

3个函数的区别如下:
(1)fopen函数打开路径名为pathname的一个指定的文件
(2)freopen函数在一个指定的流上打开一个指定的文件,如若流已经打开,则先关闭该流。
若该流已经定向,则使用freopen清楚该定向。
(3)fdopen函数取一个已有的文件描述符,并使一个标准的I/O流与该描述符相结合。

2、type参数指定对该I/O流的读、写方式。
这里写图片描述

3、对于fdopen,type参数的已有稍有区别。
(1)因为该描述符已被打开,所以fdopen为写而打开并不截断该文件。fdopen函数不能截断它为写打开的任一文件。
(2)另外,标准I/O追加写方式也不能用于创建文件(因为一个描述符引用一个文件,则该文件一定存在)。

4、当读和写类型打开一个文件时,(type中+号),具有下列限制
(1)如果中间没有 fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。
(2)如果中间没有fseek、fsetpos或rewind,或者一个输入操作没有到达文件尾端,则在输入操作之后不能直接跟随输出。

5、打开一个流的6种不同的方式:
这里写图片描述

6、注意,在指定w或a类型创建一个新文件时,我们无法说明该文件的访问权限位。可以通过调整umask值来限制这些权限。

7、否则按系统默认,流被打开时是全缓冲的。若流引用终端设备,则该流是行缓冲的。

5.6 读和写流

1、一旦打开了流,则可在3种不同类型的格式化I/O中进行选择,对其进行读、写操作:
(1)每次一个字符的I/O。一次读或写一个字符,如果流是带缓冲的,则标准I/O函数处理所有缓冲。
(2)每次一行的I/O。如果想要一次读或写一行,则使用fgets和fputs。每行都以一个换行符终止。
(3)直接I/O。fread和fwrite函数支持这种类型的I/O。每次I/O操作读或写某种数量的对象,而每个对象具有指定的长度。

2、输入函数:
(1)以下3个函数可用于一次读一个字符。

#include <stdio.h>
int getc(FILE *fp);
int fgetc(FILE *fp);
int getchar(void);
                                    3个函数的返回值:若成功,返回下一个字符;若已达到文件尾端或出错,返回EOF。

(2)函数getchar等同于getc(stdin)。前两个函数的区别是,getc可被实现为宏,而fgetc不能实现为宏。这意味着几点:

  1. getc的参数不应当是具有副作用的表达式,因为它可能会被计算多次。
  2. 因为fgetc一定是一个函数,所以得到其地址。可以作为函数指针传递给另一个函数。
  3. 调用fgetc所需的时间很可能比调用getc更长,因为调用函数所需的时间长于调用宏
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值