跳转到内容

C++/Streambuf

维基教科书,自由的教学读本
< C++

streambufw: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。

参考文献

[编辑]