Very Useful C++ Stream Class






4.46/5 (13 votes)
An article about a very useful C++ stream class
Introduction
Over the years of Windows programming, I have quite often needed a MemoryStream
class to handle various text and binary data streaming tasks. I have also needed to implement my own IStream
interface, which of course must be backed by a MemoryStream
. So I wrote the CStream
class provided in this article. Since then, I have used this class in almost every project I have done. Often, I find I need to build string
s a bit at a time. CStream
makes a perfect StringBuilder
class. You'll never need to worry about memory allocation, no matter how large the stream
grows because CStream
allocates new memory as needed.
Overview
The key feature of CStream
is that it takes care of growing the internal buffer as needed. And the key to high performance is using VirtualAlloc
. This is a very fast memory allocation function created just for this sort of situation where memory is reallocated often.
CStream
implements the COM IUnknown
and IStream
interfaces*. This means you can use it wherever an IStream
is needed. In addition to the IStream
interface, there are many helper/access methods which give access to the internal buffer for example.
CStream
is implemented in Stream.h and Stream.cpp.
* The IStream
interface is not fully implemented - only the most commonly used methods.
Using CStream
Suppose you need a StringBuilder
because you need to build up a string
a bit at a time. Here's the code:
CStream strm;
strm << "This is ";
strm << "an example ";
strm << "of a multibyte ";
strm << "string builder ";
strm << "using CStream";
// NULL terminate
strm << char(0);
// now get the pointer to the stream buffer, casting it to the
correct type
PSTR pszString = (PTSTR) strm.GetBuf();
You only need to declare the CStream
and begin writing to it. You can use the overloaded <<
operator or CStream::Write
. Be sure to write a final NULL
terminator before calling CStream::GetBuf
. GetBuf
returns the internal buffer as a BYTE*
which must be cast to our desired type in this case.
Binary data streaming is accomplished using CStream::Write
, as shown in the following example:
CStream strm;
char szFilename[300];
GetModuleFileName( NULL, szFilename, sizeof(szFilename) );
CFile file( szFilename, CFile::modeRead );
BYTE buf[500];
UINT nRead;
while( nRead = file.Read( buf, sizeof(buf) ) )
{
strm.Write( buf, nRead, NULL );
}
Useful Methods
Besides GetBuf
, CStream
also has these helper methods:
GetByte
: Returns theByte
at the current position, with the option to advance the current position.GetCurPos
: Returns the current internal position.GetEndPos
: Returns the current end position. This is not the current total allocated size, but rather the highest place in the buffer which has been written to.SetEndPos
: Sets the current end position, resizing thestream
if necessary.SeekToBegin
: Sets the internal position to the beginning of thestream
.SeekToEnd
: Sets the internal position to the end of thestream
.Seek
: Sets the internal position to the indicated position in thestream
.Reset
: Resets thestream
, optionally setting the size.
Conclusion
Text and data streaming are common things to do in programming. This stream
class fills the need quite nicely. I hope you find it to be as useful as I have.
History
- 8th October, 2009: Initial version