什么是streambuf?我该如何使用它?

106

我正在尝试学习有关C++中I/O流的工作原理,但我真的很困惑应该何时使用何种流。

streambuf是什么?
stringistreamvector相比,何时使用streambuf?(我已经了解了最后三个,但不知道streambuf如何与它们进行比较(如果可以)。)


2
@Pubby:嗯,什么是“流缓冲区”?它与流或缓冲区有何不同? - user541686
3
抱歉,我不知道那指的是什么。 - user541686
1
@Mehrdad Stroustrup的《C++程序设计语言:特别版》 - moshbear
11
如果这样能让你感觉更好,我已经使用C++工作了15年,但仍然不太懂C++库中的IO部分。在我的任何一个项目中都没有机会使用它。 - Nemanja Trifunovic
我觉得这个链接的示例代码非常易于理解:http://www.cplusplus.com/reference/ios/ios/rdbuf/ - Homer6
显示剩余5条评论
2个回答

83

2
我在各处寻找能够解释streambuf的东西,就像这篇文章一样。感谢您帮助我找到它! - wvdschel
1
示例永远是最好的。谢谢。 - daparic

67

流缓冲区代表输入或输出设备,并为该设备提供了无格式I/O的低级接口。另一方面,流通过基本的无格式I/O函数以及特别是格式化I/O函数(即operator<<operator>>重载)提供了对缓冲区的更高级别包装器。流对象也可以管理流缓冲区的生命周期。

例如,文件流具有内部文件流缓冲区。流管理缓冲区的生命周期,而缓冲区则提供实际的读写功能。流的格式化运算符最终访问流缓冲区的无格式I/O函数,因此您只需要使用流的I/O函数,而不需要直接操作缓冲区的I/O函数。

另一种理解差异的方法是观察它们使用语言环境对象的不同方式。流使用与格式化相关的facet比如numpunctnum_get。您还可以期望自定义时间或货币数据类型的流operator<<operator>>重载使用时间和货币格式facet。流缓冲区,然而,使用codecvt facet来在它们的接口使用的单位和字节之间进行转换。因此,例如,basic_streambuf<char16_t>的接口使用char16_t,因此basic_streambuf<char16_t>默认内部使用codecvt<char16_t,char,mbstate_t>将写入缓冲区的格式化char16_t单位转换为写入底层设备的char单位。因此,您可以看到流主要用于格式化,而流缓冲区为设备提供了无格式输入或输出的低级接口,该设备可能会使用不同的外部编码。

当您只需要对I/O设备进行无格式访问时,可以使用流缓冲区。如果您想设置共享流缓冲区的多个流(尽管您必须仔细管理缓冲区的生命周期),也可以使用流缓冲区。还有一些特殊用途的流缓冲区,例如C++11中的wbuffer_convert,其充当basic_streambuf<char> 的外观,以使其看起来像宽字符流缓冲区。它使用构造时附加的codecvt facet,而不是使用任何语言环境附带的codecvt facet。通常,通过使用带有适当facet的locale的宽流缓冲区,您也可以实现相同的效果。


28
这是晚了5年,所以我不会将其发布为答案并取消接受此答案,但如果任何人在阅读此后仍然对术语感到困惑:streambuf 用于处理原始数据(例如原始字节、原始整数等),而stream用于处理处理过的数据(文本、格式化为文本的整数等)。换句话说,stream代表了解析(或序列化)层。当处理纯字符串时,你可以使用其中任何一个,但含义是不同的:streambuf表示你希望原始数据就是字符串本身,而stream则抽象出编码方式。 - user541686
1
@Mehrdad,我可以问一下说“stream抽象了编码”的意思是什么吗? :D 你能再解释一下或提供更多的资料吗? - Rick
6
@Rick:好的。stream 负责读写对象streambufstreambuf 负责从一个字节存储位置保存和恢复字节(或字符/单词/您想称呼的任何东西)。将对象和字节进行映射就是我所说的“编码”。例如,stream 将接受一个 int,并决定如何将其转换为 char,反之亦然——它可以使用大端格式、小端格式、位反转格式、仅限 7 位的格式或其他任何格式。也就是说,它抽象了存储格式。 - user541686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接