
January 5th, 2007, 12:15 AM
| | | Clean binary stream
I have a solution for this, but it feels wrong. If anyone could offer
a better one, I'm all ears. (Or technically, eyes.)
Basically, I have a bunch of classes. For concreteness, one is a
Matrix class, but that's only one example, so please don't get too hung
up on it.
I need to output and input these classes. I'd like a nice, pretty,
human readable output, something like:
1 2 3
4 5 6
(note spaces and new lines).
For speed purposes (and yes, I have measured this, and yes, it does
make a difference), I also want a compressed binary version, which
would look like this:
<rows><columns><num>*
(note: no delimiters, you get all the info from the rows and columns).
I definitely need to read and write the binary version, but for some
classes I don't need to read the human readable version.
So what I have looks like this:
/// Output in textual format
std::ostream& operator<<(std::ostream& os, const Matrix& m);
/// Output in binary format
BinaryOStream& operator<<(BinaryOStream& os, const Matrix& m);
where BinaryOStream is defined like this:
class BinaryOStream
{
public:
/** The underlying ofstream wrapped by this class. */
std::ofstream m_out;
public:
/// Create a BinaryOStream from a given filename.
BinaryOStream(const std::string& filename);
~BinaryOStream(void){}
//etc
}
and its constructor opens m_out in binary mode. It also has a series
of non-member << operators for different data types (some of which are
implemented as a template).
What I don't like about the current solution is that I wind up writing
what feels like twice as much code as I should have to. Especially if
I need to read in the format (and Matrix is a bad example for this), it
seems like for most of my classes, the same input should work for both
(imagine another class where the outputs are the same except that the
text has spaces and newlines - I won't cut and paste the code here, but
you get the idea).
I kind of feel like BinaryOStream should inherit from ostream, and
implement the decorator pattern; that way I'd just write stuff for
ostream, and overload for BinaryOStream if I need to, but I can't quite
figure out how to make that work. (In particular, I would love to be
able to output stuff to a 'binary ostringstream' for testing purposes,
instead of to an actual file.)
Has anyone done this sort of thing before, and if so, found a clean
solution?
Michael | 
January 5th, 2007, 09:25 AM
| | | Re: Clean binary stream
Michael napsal: Quote:
I have a solution for this, but it feels wrong. If anyone could offer
a better one, I'm all ears. (Or technically, eyes.)
>
Basically, I have a bunch of classes. For concreteness, one is a
Matrix class, but that's only one example, so please don't get too hung
up on it.
>
I need to output and input these classes. I'd like a nice, pretty,
human readable output, something like:
1 2 3
4 5 6
(note spaces and new lines).
>
For speed purposes (and yes, I have measured this, and yes, it does
make a difference), I also want a compressed binary version, which
would look like this:
<rows><columns><num>*
(note: no delimiters, you get all the info from the rows and columns).
>
I definitely need to read and write the binary version, but for some
classes I don't need to read the human readable version.
>
So what I have looks like this:
>
/// Output in textual format
std::ostream& operator<<(std::ostream& os, const Matrix& m);
/// Output in binary format
BinaryOStream& operator<<(BinaryOStream& os, const Matrix& m);
>
where BinaryOStream is defined like this:
class BinaryOStream
{
public:
/** The underlying ofstream wrapped by this class. */
std::ofstream m_out;
>
public:
/// Create a BinaryOStream from a given filename.
BinaryOStream(const std::string& filename);
~BinaryOStream(void){}
>
//etc
}
>
and its constructor opens m_out in binary mode. It also has a series
of non-member << operators for different data types (some of which are
implemented as a template).
>
What I don't like about the current solution is that I wind up writing
what feels like twice as much code as I should have to. Especially if
I need to read in the format (and Matrix is a bad example for this), it
seems like for most of my classes, the same input should work for both
(imagine another class where the outputs are the same except that the
text has spaces and newlines - I won't cut and paste the code here, but
you get the idea).
>
I kind of feel like BinaryOStream should inherit from ostream, and
implement the decorator pattern; that way I'd just write stuff for
ostream, and overload for BinaryOStream if I need to, but I can't quite
figure out how to make that work. (In particular, I would love to be
able to output stuff to a 'binary ostringstream' for testing purposes,
instead of to an actual file.)
>
Has anyone done this sort of thing before, and if so, found a clean
solution?
>
Michael
| Hi.
Stream operator<< is not meant for binary output. It is designed for
formatted output (no matter of ios::binary - on many systems it has no
special meaning).
If you really need binary format, you should use ostream::read and
ostream::write methods. But it has many issues - you have to care about
sizes of types, because there is no guarantee, how many bytes exactly
occupies int, long ot other standard types on different platforms. You
have to care about endianity too. If you ignore these issues, you will
produce non-portable code and it will not probably work for example on
64-bit systems and 32-bit systems. |
Posting Rules
| You may not post new threads You may not post replies You may not post attachments You may not edit your posts HTML code is Off | | | | | | What is Bytes?
We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights.
Get the best answers to your questions from over network members.
|