Click here to Skip to main content
15,886,963 members
Articles / Programming Languages / C++
Article

Very Useful C++ Stream Class

Rate me:
Please Sign up or sign in to vote.
4.46/5 (14 votes)
18 Oct 2009CPOL2 min read 55.7K   1K   43   14
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 strings 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:

C++
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:

C++
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 the Byte 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 the stream if necessary.
  • SeekToBegin: Sets the internal position to the beginning of the stream.
  • SeekToEnd: Sets the internal position to the end of the stream.
  • Seek: Sets the internal position to the indicated position in the stream.
  • Reset: Resets the stream, 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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) EzTools Software
Australia Australia
I'm EzTools Software, a small software company in Perth, Western Australia. I've created some interesting and hopefully useful tools and technology, which you can see at www.eztools-software.com.

Comments and Discussions

 
GeneralMy vote of 1 Pin
lefteris2-Aug-16 4:25
lefteris2-Aug-16 4:25 
GeneralMy vote of 3 Pin
Vladimir Svyatski10-Feb-15 11:00
professionalVladimir Svyatski10-Feb-15 11:00 
QuestionWhy not use CMemMapFile ? Pin
hw7704112-Nov-09 6:10
hw7704112-Nov-09 6:10 
QuestionWhy not use std::stringstream? Pin
Owen Lawrence20-Oct-09 5:04
Owen Lawrence20-Oct-09 5:04 
AnswerRe: Why not use std::stringstream? Pin
Brett Goodman20-Oct-09 22:41
Brett Goodman20-Oct-09 22:41 
GeneralRe: VirtualAlloc Pin
Emilio Garavaglia21-Oct-09 4:30
Emilio Garavaglia21-Oct-09 4:30 
GeneralRe: VirtualAlloc Pin
Brett Goodman21-Oct-09 15:43
Brett Goodman21-Oct-09 15:43 
GeneralRe: VirtualAlloc Pin
Stefan_Lang29-Oct-09 0:34
Stefan_Lang29-Oct-09 0:34 
If your memeory handling routines take very long, check them for deallocation, not allocation! I did have a few performance issues when I switched our project's code from Malloc/free to new/delete. When I systematically analyzed the issue, I found that the original code didn't quite deallocate quite as much as it should, and that was the real problem: When dealing with memory in the range of hundreds of MB, both delete and free() take about 10-20 times as long to complete as the corresponding alloc() and new routines do! When you run low on memory the amount of time delete and free take becomes even more exorbitant, whereas the time needed for allocation stays mostly the same.

The reason for this is the system's memory manager that keeps track of the memory chunks being used by everyone, and to that end maintains lists of allocated and free memory blocks. It turns out that finding a specific allocated block that you want to free, and removing it from the allocation list becomes increasingly more expensive, the more your program allocates and frees memory chunks. Allocating memory however is relatively easy, as you just need to find the first memory block large enough to fit your size requirements.
AnswerRe: Why not use std::stringstream? Pin
domehead21-Oct-09 14:35
domehead21-Oct-09 14:35 
GeneralRe: Why not use std::stringstream? Pin
Brett Goodman21-Oct-09 15:44
Brett Goodman21-Oct-09 15:44 
QuestionIsn't there an API for this? Pin
waleri20-Oct-09 1:17
waleri20-Oct-09 1:17 
GeneralNice. A suggestion though... Pin
Arman S.19-Oct-09 17:03
Arman S.19-Oct-09 17:03 
GeneralRe: Nice. A suggestion though... Pin
RDABC20-Oct-09 3:53
RDABC20-Oct-09 3:53 
GeneralRe: Nice. A suggestion though... Pin
Brett Goodman20-Oct-09 22:46
Brett Goodman20-Oct-09 22:46 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.