Sign in to follow this  
MatsVed

C++ BinaryReader equivalent?

Recommended Posts

Does the C++ STL have an equivalent of C#'s BinaryReader and MemoryStream? I'm trying to read from an array of char[]. A BinaryWriter would also be nice! I'm tried to Google for these things, but I just get results for C++ .NET, which is not what I want. For those who don't know, BinaryReader is a streamreader that reads binary data, and MemoryStream is a streamobject that can encapsulate a bytearray.

Share this post


Link to post
Share on other sites
The STL does have streams, but from what I know no binary ones. You can use i/o fstream to read binary files, but there's no generic stream reader that only encapsulates reading/writing, no matter what the source/sink may be.

Neither does the boost i/o library (as far as I know). That's why I've written my own reader/writer that integrates into the boost i/o library (to make use of their sources/sinks).

I can send you my source if you want. But I'm curious if there's something else to use...

Share this post


Link to post
Share on other sites
The C++ iostreams work fine for binary data. Just make sure to open with the "b" mode to prevent line-ending translation. If you want to read from char[], you can either copy it into a string and use stringstream, or write a small streambuf subclass to use the data in-place.

Share this post


Link to post
Share on other sites
I'm sorry for providing this mis-information. I must have overlooked that feature. I though opening in binary mode was only available for the file streams.
From this link I get that you can provide the necessary parameter in the constructor of stringstream.

Share this post


Link to post
Share on other sites
In C/C++ you just have to setup your own little classes for that functionality. Those two classes are definitely something thing I loved about .Net when I was working on some network code in it. They are invaluable and are provided to you so you don't have to code them yourself. There are many ways to go about the task in C++, but here's the approach I use (a mixture if C/C++ constructs).

But first, disclaimers:
- The code might still have bugs in it. It's still a work in progress as I am using it and generally improving the API for it.
- The code makes uses of exceptions, so you need to use exception handling mechanisms when you use the class.
- The code is provided only for educational purposes in showing a specific approach. You should understand the concepts first before using it and eventually come up with your own solution that fits your needs.
- Finally, there might be better, more efficient, more C++'ish approaches, but I'm using what fits my needs the best, as best I could code a solution.

<Code removed since it's not needed and still a WIP>

Just throwing that out there! [smile]

[edit] Small bug fix with readonly not getting set.

[Edited by - Drew_Benton on September 17, 2009 10:02:31 AM]

Share this post


Link to post
Share on other sites
Ok, now I've come up with a BinaryStream that works more or less thi way I need it to.
But there's a problem - how do I convert an integer number to a char array?
I don't want the ASCII representation of the number (meaning I can't use itoa()), but the binary representation.

Here's what I tried to do so far:

void BinaryStream::WriteInt(int Int)
{
for(int i = 0; i < 4; i++)
{
m_Buffer[m_BufPosition] = (int*)Int[i];
m_BufPosition++;
}
}



It didn't work. Compiler complains that using subscripts needs pointers or array types, so I tried casting the int to a pointer, which didn't work either.
If you want to see what m_Buffer and m_BufPosition looks like, here's my class definition:

/*===============================================================================================================
/*
/* Class name: BinaryStream
/* Purpose: Provide an interface for reading basic types (int, uint, char etc) from char arrays
/*
/*==============================================================================================================*/


class BinaryStream
{
private:
char *m_Buffer;
int m_BufPosition;
public:
BinaryStream(char *Buf[]);

char ReadByte();
char* ReadBytes(int NumBytes);
int ReadInt();
unsigned int ReadUInt();
short ReadShort();

void WriteByte(char Byte);
void WriteBytes(char *Bytes[], int Length);
void WriteInt(int Int);
void WriteUInt(unsigned int UInt);
void WriteShort(short Short);
};



Edit: Yes, I tried to Google the answer - and most of the ones I found were based around converting the integer to it's ASCII equivalent.

Share this post


Link to post
Share on other sites
The integer is already in memory exactly how you want it, so all you really need to do is get a pointer to it and then convert the pointer to a char*. Or you could just memcpy the integer into your buffer (which does all of the convert-pointers-and-copy for you).

The simplest way is to do this:


template <typename T>
void WritePODType(T value)
{
memcpy(m_Buffer+m_BufPosition, &value, sizeof(value));
m_BufPosition += sizeof(value);
}

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
The C++ iostreams work fine for binary data. Just make sure to open with the "b" mode to prevent line-ending translation.


And by "b" you mean std::ios::binary, yes? :)

(It also prevents interpretation of a certain character as an EOF marker.)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this