C++/Streambuf
streambuf 是w:C++标准程式库中的一个w:头文件,定义了C++标准中的流输入输出的基本模板类std::basic_streambuf。这是一个虚基类,用于派生具体的流缓冲区类。
简介
[编辑]std::basic_streambuf中,用“开始位置”、“当前位置”、“结尾位置”3个属性描述输入或输出缓冲区。在此之上定义了大量的非常基本的流缓冲区的常用操作函数,如读/写一个字符、读n个字符、重定位当前指针、设置缓冲区的w:locale、设置锁操作等等。其中具有公共访问属性的成员函数对所有流缓冲区是常用的;保护访问属性的w:虚成员函数需要在针对特定流缓冲区的派生类中有专门的实现。其它保护属性的非虚成员函数是对流缓冲区的一些基本操作,如获得缓冲区开始指针、当前指针、尾部指针等等。 C++标准库中的其它流输入输出一般都是派生于std::basic_streambuf基类。
所有的流缓冲区实现遵循下属约定:
- 受控字符序列(controlled character sequence),也称作缓冲区,可包括:输入序列(也称get area)用于缓冲输入操作;以及输出序列(也称put area)用于缓冲输出操作。
- 被关联的字符序列(associated character sequence),也称源(source)用于输入或者汇(sink)用于输出。它可以是各种实体,如通过操作系统API访问的文件,TCP socket,串口,其它字符设备;或者是一个对象(std::vector,array,stringw:字面量等)可被解释为字符源或汇。
- 受控字符序列由3种指针描述:
- 开始指针eback或pbase,总是指向缓冲区的地址最低元素。
- 当前指针gptr或pptr(也称作next pointer)指向下一个将要读/写的数据对象。如果next pointer为空,则缓冲区不存在;否则,可以安全比较缓冲区的开始指针、next pointer、尾指针的先后顺序。
- 对于输出缓冲区,如果next pointer小于尾指针,则可以在next pointer所指位置处存入一个数据。
- 对于输入缓冲区,如果next pointer小于尾指针,则可以在next pointer所指位置处读入一个数据。
- 对于输入缓冲区,如果开始指针小于next pointer,可以在next pointer所指的回退位置(putback position)处回退仿制(put back)一个数据。
- 尾指针egptr或epptr(end pointer),指向缓冲区结尾后的下一个字符。
受控字符序列的字符表示与编码可能与被关联的字符序列不同。这种情况下典型使用一种w:locale facet:std::codecvt执行字符转码。如把UTF-8或其他多字节编码文件通过std::wfstream对象读入,这时受控字符序列由宽字符组成,但被关联的字符序列由字节组成。
std::basic_streambuf的典型实现仅保持6个CharT*指针与一个std::locale拷贝作为数据成员。
streambuf
头文件中还定义了basic_streambuf的两个模板特化实例,分别针对字符类型与宽字符类型:
- typedef basic_streambuf<char, char_traits<char> > streambuf;
- typedef basic_streambuf<wchar_t, char_traits<wchar_t> > wstreambuf;
成员类型
[编辑]成员类型 | 定义 |
---|---|
char_type | CharT |
traits_type | Traits |
int_type | Traits::int_type |
pos_type | Traits::pos_type |
off_type | Traits::off_type |
成员函数
[编辑]- 虚析构函数:
- Locales
- pubimbue:调用最派生类的imbue()
- getloc:获取流当前使用的locale。
- 定位
- pubsetbuf:调用setbuf()
- pubseekoff:调用seekoff()
- pubseekpos:调用seekpos()
- pubsync:调用sync()
- 输入缓冲区(Get area)
- in_avail:获取在输入缓冲区直接可利用字符数量。
- snextc:推进指针一步,然后返回新的位置处的值
- sbumpc:读出当前位置的值,然后推进指针一步。如果缓冲区的内容已经读完,那么sbumpc会调用uflow方法
- stossc:过时。推进指针一步
- sgetc:读出当前位置的值,指针不变。如果缓冲区的内容已经读完,那么sgetc会调用underflow方法
- sgetn:调用xsgetn() 用于读取多个字符
- 输出缓冲区(Put area)
- sputc:向输出缓冲区写入一个字符,然后推进指针一步。如果缓冲区已经满了或者没有提供缓冲区,sputc会调用overflow,将数据写入外部的汇并清空缓冲区。
- sputn:输出多个字符。实际调用xsputn() ,而xsputn的默认操作是对每个字符调用sputc。
- 放回(Putback)
- sputbackc:把一个字符放回到输入缓冲区
- sungetc:输入缓冲区的指针向回移动一步,然后返回当前位置的值
- protected成员函数
- 构造函数
- operator=
- swap
- Locales
- imbue
- 定位
- setbuf:基类的该函数为空操作。派生类可重载此虚函数用自定义的缓冲区替换缺省的缓冲区。
- seekoff:基类的该函数为空操作。派生类可重载此虚函数,对缓冲区的当前指针相对寻址。
- seekpos:基类的该函数为空操作。派生类可重载此虚函数,对缓冲区的当前指针绝对寻址。
- sync:同步受控字符序列(即缓冲区)与被关联的字符序列。对输出缓冲区,典型是把其内容写入到被关联的序列;对输入缓冲区,典型是放弃当前输入缓冲区的内容,重新从被关联序列读入最新内容到输入缓冲区。
- 输入缓冲区(Get area)
- showmanyc
- underflow
- uflow 默认行为是调用underflow,然后移动缓冲区的读取指针
- xsgetn 默认行为是依次调用sbumpc,如果为了改善读取多个字符的性能,可以重写xsgetn方法
- eback 输入缓冲区开始位置
- gptr 输入缓冲区当前位置
- egptr 输入缓冲区结束位置
- gbump 推进get指针
- setg 设置输入序列指针
- 输出缓冲区(Put area)
- xsputn
- overflow
- pbase 输出缓冲区开始位置
- pptr 输出缓冲区当前位置
- epptr 输出缓冲区结束位置
- pbump 增加当前写入位置的指针
- setp 设置当前写入位置的指针
- 放回(Putback)
- pbackfail
其它辅助模板类
[编辑]streambuf
头文件中还定义了模板类std::istreambuf_iterator,用于描述从输入流中读取数据对象的基本操作。它从相关联的basic_streambuf,定义了解引用(dereference)的*操作符、前缀++操作符、后缀++操作符、equal成员函数。
streambuf
头文件中还定义了模板类std::ostreambuf_iterator,用于描述向输出流中写入数据对象的基本操作。它关联一个输出流basic_streambuf,定义了写入一个字符的赋值操作符。其它操作符,如解引用(dereference)的*操作符、前缀++操作符、后缀++操作符,都是简单地返回iterator自身。还定义了failed成员函数,查看写入操作是否成功的内部标志位_Failed。