首页 理论教育 流缓冲区的功能及接口分析

流缓冲区的功能及接口分析

时间:2023-10-25 理论教育 版权反馈
【摘要】:通常,stream并不负责实际读写操作,而是委托给流缓冲区实现。输出流将某些字符放入缓冲区。此类缓冲区被称为流缓冲区。将512个Byte收集到缓冲区中,之后一次性将其写入硬盘的效率,这才是他们所期望的。例如,换行符发送至缓冲区之后,缓冲区即被刷新。而多数的C++语言,是在输入即将发生时,刷新缓冲区。访问流缓冲区的接口非常复杂。如果调用出错,函数返回0;否则,返回该stream缓冲区。

流缓冲区的功能及接口分析

通常,stream并不负责实际读写操作,而是委托给流缓冲区实现。输出流将某些字符放入缓冲区。之后于某个时刻,这些字符被写至输出设备上。此类缓冲区被称为流缓冲区。类streambuf为缓冲区管理内存,并提供用于填充的缓冲区、访问缓冲区内容、刷新缓冲区和管理缓冲区内存的类方法。

在使用cout输出字符时,刷新输出缓冲区具有一定的意义。由于ostream类对cout对象处理的输出进行缓冲,输出不会立即发送到目标地址,而被存在缓冲区中,直至缓冲区被填满。之后,程序通过刷新缓冲区,将其中的内容发送出去,并清空缓冲区,以存储新的数据。通常,缓冲区的大小为512Byte或其整数倍。当标准输出连接的是硬盘上的文件时,缓冲可以节省大量时间。程序员不希望程序为发送512Byte而存取磁盘512次。将512个Byte收集到缓冲区中,之后一次性将其写入硬盘的效率,这才是他们所期望的。

对于屏幕输出,首先填充缓冲区的重要性要低得多。幸运的是,屏幕输出时,程序没必要等待缓冲区被填充。例如,换行符发送至缓冲区之后,缓冲区即被刷新。而多数的C++语言,是在输入即将发生时,刷新缓冲区。控制符flush和endl均可实现刷新缓冲区,而控制符endl在刷新缓冲区时,还将插入一个换行符。

对于程序员来说,类basic_streambuf仅仅是发送(sent)或提取(extracted)字符的地方。通常有两个公共函数用于写入字符。它们是sputc()和sputn()。sputc()函数调用发生错误时,会返回traits_type::eof(),之后traits_type是类中的型别定义。sputn()函数将写入由第二参数指定的字符数,除非stream缓冲区无法使用该字符。这两个函数在使用过程中,是不考虑字符串终止符号的。其返回值是实际写出的字符数。

访问流缓冲区的接口非常复杂。对于输入而言,必须时刻监视未耗用的字符。解析时,字符最好能被送回stream缓冲区。为此,类streambuf特别提供了相应的成员函数,详见表7-3。

7-3streambuf的成员函数(输入)

978-7-111-51399-5-Chapter07-73.jpg

in_vail()函数用于确定缓冲区中至少有多少个有效字符。用于确定从键盘读取数据时不会发生阻塞。值得注意的是,缓冲区实际上可能包含更多的有效字符。

函数sgetc()不必移动至下一字符即可获得当前字符sbumpc()函数读取当前字符并移动至下一个字符,并使之成为当前字符。snextc()函数将下一个字符视为当前字符,之后读取之。这3个函数如果调用失败,均会返回traits_type::eof()。sgetn()函数读取字符序列并发送至缓冲区中,其参数可以代表欲读取的字符数,返回值是实际读取的字符数目。(www.xing528.com)

sputbackc()和sungetc()函数被用于后退一步,并使前一个字符成为当前字符。sput- backc()函数可将前一字符替换为其他字符。使用这两个函数,只能回退一个字符。还有部分函数用于存取局部对象,改变位置或影响缓冲区,详见表7-4。

7-4 难以分类的类streambuf的公用函数

978-7-111-51399-5-Chapter07-74.jpg

pubimbue()和getloc()用于国际化议题。pubimbue()在stream缓冲区中安装一个新的locale对象,并返回前一个被安装的locale对象:getloc()返回当前的locale对象。

pubsetbuf()函数试图对缓冲区的缓冲策略进行控制,是否有效则取决于具体的类stre- ambuf。例如,对于字符串流缓冲区运用pubsetbuf()将毫无意义。即使用于文件流缓冲区,也只能在第一个IO操作之后以pubsetbuf(0,0)方式调用才起作用。如果调用出错,函数返回0;否则,返回该stream缓冲区。

pubseekoff()函数和pubseekpos()函数控制读写操作的当前位置,无论控制读或写,都取决于最后一个参数(型别为ios_base::openmode),如果没有特别指定,参数默认值为ios_base::in|ios_base::out。一旦设置ios_base::in,读取位置会跟着改变;一旦设置ios_base::out,改写位置会跟着变化。pubseekpos()函数会把stream当前位置移动至其第一个参数指示的绝对位置上;pubseekoff()函数会把stream当前位置移动至相对位置,偏移量由第一个参数决定,起始位置由第二参数决定,标识符一般是ios_base::cur/ios_base::beg/ios_base::end。这两个函数均返回stream所在位置或无效位置,将函数结果拿来和对象pos_type比较,检查出无效的stream位置。如果要获取stream的当前位置,需要使用pubseekoff()函数。例如,

978-7-111-51399-5-Chapter07-75.jpg

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈