What exactly is streambuf? How do I use it?
Asked Answered
M

2

106

I'm trying to learn a bit more about how I/O streams work in C++, and I'm really confused at when to use what.

What exactly is a streambuf?
When do I use a streambuf, as compared to a string, an istream, or a vector? (I already know the last three, but not how streambuf compares to them, if it does at all.)

Malpighiaceous answered 14/11, 2011 at 2:5 Comment(10)
It's a bad abstraction of a stream buffer.Emplace
@Pubby: Er, what's a "stream buffer"? How is it different from a stream or a buffer?Malpighiaceous
From what I understand, a stream formats the in/output and stores it in it's buffer.Emplace
Read TC++PL SE (S) 21.6.Thyrsus
@moshbear: Sorry, I have no idea what that's referring to.Malpighiaceous
@Mehrdad Stroustrup's The C++ Programming Language: Special EditionThyrsus
@moshbear: Oh... I'll buy that when I get the chance I guess, thanks.Malpighiaceous
It's to C++ as K&R is to C. That good.Thyrsus
If that is going to make you feel any better, I've worked with C++ for 15 years and still don't get the IO part of the C++ library. There wasn't a single project where I had a chance to use it.Atrophy
I found this link's example code was pretty explanatory: cplusplus.com/reference/ios/ios/rdbufStreamway
B
67

Stream buffers represent input or output devices and provide a low level interface for unformatted I/O to that device. Streams, on the other hand, provide a higher level wrapper around the buffer by way of basic unformatted I/O functions and especially via formatted I/O functions (i.e., operator<< and operator>> overloads). Stream objects may also manage a stream buffer's lifetime.

For example a file stream has an internal file stream buffer. The stream manages the lifetime of the buffer and the buffer is what provides actual read and write capabilities to a file. The stream's formatting operators ultimately access the stream buffer's unformatted I/O functions, so you only ever have to use the stream's I/O functions, and don't need to touch the buffer's I/O functions directly.

Another way to understand the differences is to look at the different uses they make of locale objects. Streams use the facets that have to do with formatting such as numpunct and num_get. You can also expect that the overloads of stream operator<< and operator>> for custom time or money data types will use the time and money formatting facets. Stream buffers, however, use the codecvt facets in order to convert between the units their interface uses and bytes. So, for example, the interface for basic_streambuf<char16_t> uses char16_t and so basic_streambuf<char16_t> internally uses codecvt<char16_t, char, mbstate_t> by default to convert the formatted char16_t units written to the buffer to char units written to the underlying device. So you can see that streams are mostly for formatting and stream buffers provide a low level interface for unformatted input or output to devices which may use a different, external encoding.

You can use a stream buffer when you want only unformatted access to an I/O device. You can also use stream buffers if you want to set up multiple streams that share a stream buffer (though you'll have to carefully manage the lifetime of the buffer). There are also special purpose stream buffers you might want to use, such as wbuffer_convert in C++11 which acts as a façade for a basic_streambuf<char> to make it look like a wide character stream buffer. It uses the codecvt facet it's constructed with instead of using the codecvt facet attached to any locale. You can usually achieve the same effect by simply using a wide stream buffer imbued with a locale that has the appropriate facet.

Bruiser answered 14/11, 2011 at 4:4 Comment(3)
This is 5 years too late, so I'm not going to post it as an answer and un-accept this one, but for anyone still confused by the terminology even after reading this: streambuf is for raw data (e.g. raw bytes, raw ints, etc.), whereas stream is for cooked data (text, integers formatted as text, etc.). Put another way, stream represents the parsing (or serialization) layer. When dealing with plain strings, you can technically use either, but the meaning is different: streambuf means you want the raw data to be the string itself, whereas stream abstracts away the encoding.Malpighiaceous
@Mehrdad May I ask what does it mean by saying stream abstracts away the encoding? :D Can you explain it a little bit more or provide some further material?Ministration
@Rick: Sure. stream is responsible for reading and writing objects to a streambuf. streambuf is responsible for saving and restoring bytes (or chars/words/whatever you prefer to call them) from a byte-storage location. The mapping between objects and bytes is what I was referring to as the "encoding". An example of this is that a stream would accept an int and then decide how to convert that into chars, and vice-versa -- it could use big-endian format, little-endian format, a bit-reversed format, a 7-bit-only format, or anything else. i.e. it abstracts away the storage format.Malpighiaceous
P
84

With the help of streambuf, we can work in an even lower level. It allows access to the underlying buffers.

Here are some good examples : Copy, load, redirect and tee using C++ streambufs and in reference to comparison, This might be helpful,

enter image description here

See this for more details : IOstream Library

Physic answered 14/11, 2011 at 2:36 Comment(2)
I searched all over for something that could explain streambuf's as well as this article. Thanks for helping me find it!Ewan
Example is always best. Thank youEyot
B
67

Stream buffers represent input or output devices and provide a low level interface for unformatted I/O to that device. Streams, on the other hand, provide a higher level wrapper around the buffer by way of basic unformatted I/O functions and especially via formatted I/O functions (i.e., operator<< and operator>> overloads). Stream objects may also manage a stream buffer's lifetime.

For example a file stream has an internal file stream buffer. The stream manages the lifetime of the buffer and the buffer is what provides actual read and write capabilities to a file. The stream's formatting operators ultimately access the stream buffer's unformatted I/O functions, so you only ever have to use the stream's I/O functions, and don't need to touch the buffer's I/O functions directly.

Another way to understand the differences is to look at the different uses they make of locale objects. Streams use the facets that have to do with formatting such as numpunct and num_get. You can also expect that the overloads of stream operator<< and operator>> for custom time or money data types will use the time and money formatting facets. Stream buffers, however, use the codecvt facets in order to convert between the units their interface uses and bytes. So, for example, the interface for basic_streambuf<char16_t> uses char16_t and so basic_streambuf<char16_t> internally uses codecvt<char16_t, char, mbstate_t> by default to convert the formatted char16_t units written to the buffer to char units written to the underlying device. So you can see that streams are mostly for formatting and stream buffers provide a low level interface for unformatted input or output to devices which may use a different, external encoding.

You can use a stream buffer when you want only unformatted access to an I/O device. You can also use stream buffers if you want to set up multiple streams that share a stream buffer (though you'll have to carefully manage the lifetime of the buffer). There are also special purpose stream buffers you might want to use, such as wbuffer_convert in C++11 which acts as a façade for a basic_streambuf<char> to make it look like a wide character stream buffer. It uses the codecvt facet it's constructed with instead of using the codecvt facet attached to any locale. You can usually achieve the same effect by simply using a wide stream buffer imbued with a locale that has the appropriate facet.

Bruiser answered 14/11, 2011 at 4:4 Comment(3)
This is 5 years too late, so I'm not going to post it as an answer and un-accept this one, but for anyone still confused by the terminology even after reading this: streambuf is for raw data (e.g. raw bytes, raw ints, etc.), whereas stream is for cooked data (text, integers formatted as text, etc.). Put another way, stream represents the parsing (or serialization) layer. When dealing with plain strings, you can technically use either, but the meaning is different: streambuf means you want the raw data to be the string itself, whereas stream abstracts away the encoding.Malpighiaceous
@Mehrdad May I ask what does it mean by saying stream abstracts away the encoding? :D Can you explain it a little bit more or provide some further material?Ministration
@Rick: Sure. stream is responsible for reading and writing objects to a streambuf. streambuf is responsible for saving and restoring bytes (or chars/words/whatever you prefer to call them) from a byte-storage location. The mapping between objects and bytes is what I was referring to as the "encoding". An example of this is that a stream would accept an int and then decide how to convert that into chars, and vice-versa -- it could use big-endian format, little-endian format, a bit-reversed format, a 7-bit-only format, or anything else. i.e. it abstracts away the storage format.Malpighiaceous

© 2022 - 2024 — McMap. All rights reserved.