【C++ IO机制】stream_buf 解析

stream_buf 解析

1. stream_buf原型:

template <class CharT, class Traits = std::char_traits<CharT>>
class basic_streambuf;

【注意】

typedef basic_streambuf<char> streambuf;

用于输出的 streambuf

streambuf 使用三个指针来管理相应的输出缓冲区(缓冲区需要自行设置),分别由接口 pbasepptr和 epptr 返回。其中 pbase 是缓冲区的基指针,指向缓冲区的第一个字节,epptr 是缓冲区的尾指针,指向其最后一个字节的下一个字节(类似于 iter.end() 的作用),而 pptr 指向缓冲区当前可用的位置,也就是pptr 之前都已经被数据所填充,如下图:

 streambuf 定义的输出相关的函数主要有 sputc 和 sputn,前者输出一个字符到缓冲区,并且将指针 pptr 向后移动一个字符,后者调用函数 xsputn 连续输出多个字符,xsputn 默认的实现就是多次调用 sputc。由于缓冲区有限,当 pptr 指针向后移动满足 pptr() == epptr 时,说明缓冲区满了,这时将会调用函数 overflow 将数据写入到外部设备并清空缓冲区;清空缓冲区的方式则是调用 pbump 函数将指针 pptr 重置。我们可以通过如下的类来实现自定义的输出 buffer:

用于输入的 streambuf

同管理输出缓冲区一样,streambuf 也使用三个指针,eback()gptr() 以及 egptr() 分别指示输入缓冲区的开始字节,当前可用字节以及缓冲区尾的下一字节,如下图所示:

streambuf 类同样定义了如下几个函数来支持对于输入缓冲区的读取和管理:

  • sgetc: 从输入缓冲区中读取一个字符;
  • sbumpc: 从输入缓冲区中读取一个字符,并将 gptr() 指针向后移动一个位置;
  • sgetn: 从输入缓冲区中读取 n 个字符;
  • sungetc: 将缓冲区的 gptr() 指针向前移动一个位置;
  • sputbackc: 将一个读取到的字符重新放回到输入缓冲区中;

与输出缓冲区不同的是,输入缓冲区需要额外提供 putback 操作,也就是将字符放回到输入缓冲区内。

 

1. 示例
 1 #include <iostream>
 2 #include <fstream>
 3 
 4 int main()
 5 {
 6   std::ifstream ifs("test.txt");
 7   if (ifs.good())
 8   {
 9     std::streambuf *pbuf = ifs.rdbuf();
10     char c;
11     ifs >> c;
12     std::streamsize size = pbuf->in_avail();
13     std::cout << "first character in file: " << c << '\n';
14     std::cout << size << " characters in buffer after it\n";
15   }
16   ifs.close();
17 
18   return 0;
19 }

说明: test.file 文件内容如下:

this is test file!

输出:

first character in file: t
18 characters in buffer after it
 1 #include <iostream>
 2 #include <sstream>
 3 
 4 int main()
 5 {
 6   std::stringstream stream("Hello, world");
 7   std::cout << "sgetc() returned '" << (char)stream.rdbuf()->sgetc() << "'\n";
 8   std::cout << "peek() returned '" << (char)stream.peek() << "'\n";
 9   std::cout << "get() returned '" << (char)stream.get() << "'\n";
10 }

输出:

sgetc() returned 'H'
peek() returned 'H'
get() returned 'H'

说明:

sgetc() 返回当前位置的字符。
sbumpc() 返回当前位置的字符,并将当前位置前进到下一个字符。
snextc() 将当前位置前进到下一个字符并返回下一个字符。

参考资料

1. std::streambuf从示例到应用

2. stream_buff 解析【cppreference.com】

3. C/C++编程:流缓冲类std::basic_streambuf

原文地址:https://www.cnblogs.com/sunbines/p/15730390.html