473,320 Members | 1,965 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

ostream implementations (str, f, cout ) work slightly differently


Hi there,
I am writing c++ for some months now. I think I know the language now, but not yet all the tricky things of stl.

For a kernel which is not using mfc I am writing a serialization. For some reasons I want to implement it on my
own.
One goal is to make it robust against version changes and corrupted files. That means, when an object cannot
be deserialized, it should be skipped. The validity of the remaining document can be verified later.
For this purpose I begin every object with a code that identifies the class. A factory can use it to construct
the class, giving it the node of the serialized stream.
The next is the size of the object. This way the object can be skipped if something is wrong. An earlier version
might not contain all the variables for a class, a later one may contain too much. The serializer or deserializer
methods of the class will have apropriate default values at hand.
The problem is that the size is of course unknown before th object is already serialized. For performance
matters I dont want to have a kind of size inquiry before the serialization and I dont want something to serialize
to another place and then copy to the real stream. Even though my files might not be going to be soo big, I
don't know what comes in the future.
So my way is to save the current stream position before the serialization, and then jump back and forth to put
the size in the right place.
My first question is: Does anyone now how costly that is? I guess not too much, but I don't really knwo about
the implementation of the streams.
Then I see that it sometimes doesn't behave as expected.
Ok, the cout can get the position it returns only zero. No problem since serializing to cout is not really useful
to me.
one might ask why I want to use this general ostream to serialize to. Well I dont know what it is going to do
later: saving docs, transaction ( undo/redo), network communication or just with another process, dragn drop...
therefore I think a general apporoach is ok.
Now the file stream sometime puts the very first int size not into the first place but shifted about one byte. THis
is weird, ugly and it corrupts the actual data. But it depends on the size of the actual data. It happens if it is
small, and depends on wether the size is odd or even !?! I tried to overcome this with an initializing "initialize"
string wich will be known and therefore needs no size info. But in this case the problem appears after this
initilaizing string. So it is something with my jumping around with the seekp() method.
The strstream is a little similar but the first data value is not corrupted. But the whole data is shifted by one bit
:-(.
So if one is really familiar with the streams: I just want to know what do I have to consider to make my code
work securely. It should not only work no, but in any case on any machine and on compilers different than my
VS.net2003 compiler
thanks for your help in advance. I tried to post source, but the server rejected. Probably too big. Ask if
necessary and I will post it
cheers
Ingo
Jul 22 '05 #1
9 2101

"Ingo Nolden" <nu************@SPAMgmx.de> wrote in message
news:c6**********@svr7.m-online.net...

Hi there,
I am writing c++ for some months now. I think I know the language now, but not yet all the tricky things of stl.
For a kernel which is not using mfc I am writing a serialization. For some reasons I want to implement it on my own.
One goal is to make it robust against version changes and corrupted files. That means, when an object cannot be deserialized, it should be skipped. The validity of the remaining document can be verified later. For this purpose I begin every object with a code that identifies the class. A factory can use it to construct the class, giving it the node of the serialized stream.
The next is the size of the object. This way the object can be skipped if something is wrong. An earlier version might not contain all the variables for a class, a later one may contain too much. The serializer or deserializer methods of the class will have apropriate default values at hand.
The problem is that the size is of course unknown before th object is already serialized. For performance matters I dont want to have a kind of size inquiry before the serialization and I dont want something to serialize to another place and then copy to the real stream. Even though my files might not be going to be soo big, I don't know what comes in the future.
So my way is to save the current stream position before the serialization, and then jump back and forth to put the size in the right place.
My first question is: Does anyone now how costly that is? I guess not too much, but I don't really knwo about the implementation of the streams.
Then I see that it sometimes doesn't behave as expected.
Ok, the cout can get the position it returns only zero. No problem since serializing to cout is not really useful to me.
one might ask why I want to use this general ostream to serialize to. Well I dont know what it is going to do later: saving docs, transaction ( undo/redo), network communication or just with another process, dragn drop... therefore I think a general apporoach is ok.
Now the file stream sometime puts the very first int size not into the first place but shifted about one byte. THis is weird, ugly and it corrupts the actual data. But it depends on the size of the actual data. It happens if it is small, and depends on wether the size is odd or even !?!


Probably you have not opened the file in binary mode. Absolute positioning
of file streams is not possible unless you do this

E.g.

ostream file("somefile.txt", ios_base::out|ios_base::binary);

john
Jul 22 '05 #2
>
E.g.

ostream file("somefile.txt", ios_base::out|ios_base::binary);


ofstream of course.

john
Jul 22 '05 #3
thank you

some times things are simple.
the file thing is working now as expected.

Is there such sthing as a binary mode for the strstream, too? Or is there some template related to the
strstream that I can use for binary data. It works nearly perfect just occasionally it shifts by a byte. Of coure I
could find a way to synchronize it somehow, even though I dont think this is how it should be done.

cheers

"John Harrison"
wrote in message: <c6************@ID-196037.news.uni-berlin.de>

E.g.

ostream file("somefile.txt", ios_base::out|ios_base::binary);


ofstream of course.

john

Jul 22 '05 #4

"Ingo Nolden" <nu************@SPAMgmx.de> wrote in message
news:c6**********@svr7.m-online.net...
thank you

some times things are simple.
the file thing is working now as expected.

Is there such sthing as a binary mode for the strstream, too? Or is there some template related to the strstream that I can use for binary data. It works nearly perfect just occasionally it shifts by a byte. Of coure I could find a way to synchronize it somehow, even though I dont think this is how it should be done.
cheers


I don't believe there is a binary mode for strstream. Text mode/binary mode
is C++'s way of dealing with different line ending conventions in different
OS. Obviously that only applies to files. I'd say that what you are seeing
in strstream is probably just a bug in your code. Why not post some code
that reproduces the problem?

BTW stringstream is usually preferred to strstream, but that has nothing to
do with binary data.

john
Jul 22 '05 #5
I can hardly believe it is the code, but I try to put it in here. Last time the server rejected. I think my
newsreader is doing something strange with the includes thinking they were an xml token...
in strstream is probably just a bug in your code. Why not post some code
that reproduces the problem?

BTW stringstream is usually preferred to strstream, but that has nothing to
do with binary data.


I thried this also. But derivation of the stringstream seams a little different to strstream as the function that
takes the ostream will also take the strstream and the ofstream but not the stringstream nor the
ostringstream. I have to admit that I don't really look through the inheritance of the stream classes

So here my code:
I replace the include brackets with " for my proggie

#include "strstream"
#include "iostream"
#include "fstream"

using namespace std;

void f( int i );

void f( int i)
{

}
class CleverStream
{
public:
CleverStream( ostream& str )
{
s = &str;
// check if position can be set:

int i = s->tellp( );

if( i == -1 )
throw exception( "Invalid stream" );

}
void SaveData( char* sData )
{
if( s == &cout )
s->seekp( 0 );
unsigned int i = 0;
unsigned int dwBefore = s->tellp( );
s->write( (char*)&i, 4 );// << (char[8])&i; // placeholder int
*s << sData;
unsigned int dwAfter = s->tellp( );
s->seekp( dwBefore );
i = dwAfter - dwBefore;
s->write( (char*)&i, 4 );
// s->flush( );
s->seekp( dwAfter );
}
void Initialize( char* sData )
{
*s << sData;
}

ostream* s;

};
void PutThings( CleverStream& s )
{
// s.Initialize( "Initializer" );
s.SaveData( "Khadij" );
s.SaveData( "Khadija und Ingo machen einen ganz langen Satzg" );
s.SaveData( "S" );
s.SaveData( "Fi" );
s.SaveData( "Dep" );
s.SaveData( "Subj" );
s.SaveData( "Final" );
}

int main( )
{

try
{
// ofstream x( "iotest.txt" );
ofstream x( "iotest.txt", ios_base::out|ios_base::binary );
CleverStream s_file( x );
PutThings( s_file );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
CleverStream s_cout( cout );

PutThings( s_cout );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
cout << endl << endl << endl;
char buf[100];
ostringstream x_str( );
ostringstream y_str( );
//strstream x_str( buf, 100 );
//strstream y_str( buf, 100 );
//strstream x_str( buf, 100 , ios_base::out|ios_base::binary);
//strstream y_str( buf, 100, ios_base::out|ios_base::binary );

CleverStream s_str( x_str );

PutThings( s_str );

ofstream y( "strtest.txt" );

y.write( x_str.str( ), x_str.pcount( ) );
}
catch ( exception e )
{
cout << e.what( );
}

return 0;
}
Jul 22 '05 #6

"Ingo Nolden" <nu************@SPAMgmx.de> wrote in message
news:c6**********@svr7.m-online.net...
I can hardly believe it is the code, but I try to put it in here. Last time the server rejected. I think my newsreader is doing something strange with the includes thinking they were an xml token...
in strstream is probably just a bug in your code. Why not post some code
that reproduces the problem?

BTW stringstream is usually preferred to strstream, but that has nothing todo with binary data.


I thried this also. But derivation of the stringstream seams a little

different to strstream as the function that takes the ostream will also take the strstream and the ofstream but not the stringstream nor the ostringstream. I have to admit that I don't really look through the inheritance of the stream classes
That's easily fixed, see comments below.
So here my code:
I replace the include brackets with " for my proggie

#include "strstream"
#include "iostream"
#include "fstream"

using namespace std;

void f( int i );

void f( int i)
{

}
class CleverStream
{
public:
CleverStream( ostream& str )
{
s = &str;
// check if position can be set:

int i = s->tellp( );

if( i == -1 )
throw exception( "Invalid stream" );

}
void SaveData( char* sData )
{
if( s == &cout )
s->seekp( 0 );
unsigned int i = 0;
unsigned int dwBefore = s->tellp( );
s->write( (char*)&i, 4 );// << (char[8])&i; // placeholder int
*s << sData;
unsigned int dwAfter = s->tellp( );
s->seekp( dwBefore );
i = dwAfter - dwBefore;
s->write( (char*)&i, 4 );
// s->flush( );
s->seekp( dwAfter );
}
void Initialize( char* sData )
{
*s << sData;
}

ostream* s;

};
void PutThings( CleverStream& s )
{
// s.Initialize( "Initializer" );
s.SaveData( "Khadij" );
s.SaveData( "Khadija und Ingo machen einen ganz langen Satzg" );
s.SaveData( "S" );
s.SaveData( "Fi" );
s.SaveData( "Dep" );
s.SaveData( "Subj" );
s.SaveData( "Final" );
}

int main( )
{

try
{
// ofstream x( "iotest.txt" );
ofstream x( "iotest.txt", ios_base::out|ios_base::binary );
CleverStream s_file( x );
PutThings( s_file );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
CleverStream s_cout( cout );

PutThings( s_cout );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
cout << endl << endl << endl;
char buf[100];
ostringstream x_str( );
ostringstream y_str( );
I think you mean

ostringstream x_str;
ostringstream y_str;

What you had is a function prototype, not a variable declaration.

You also need to change the header from "strstream" to "sstream".
//strstream x_str( buf, 100 );
//strstream y_str( buf, 100 );
//strstream x_str( buf, 100 , ios_base::out|ios_base::binary);
//strstream y_str( buf, 100, ios_base::out|ios_base::binary );

CleverStream s_str( x_str );

PutThings( s_str );

ofstream y( "strtest.txt" );

y.write( x_str.str( ), x_str.pcount( ) );


With strstream this is a memory leak, its one of the main arguments against
strstream that after calling str() you have to free the returned pointer.

For stringstream this becomes

y.write( x_str.str( ).c_str(), x_str.str( ),size() );

and no memory leak.

However even with these fixes I couldn't get ostringstream to work. The
problem is your test to see if a stream is positionable. On my system seekp
returns -1 before any output has happened even though ostringstream is
positionable (the reason being that the output buffer isn't actually
allocated until some output has occurred). I'm not sure if this is correct
behaviour or not. If you remove the test, or if you do some output before
making the test then everything works.

john
Jul 22 '05 #7


thank you John for your efforts. Indeed it works nearly in any case. Unless the first "counted" output has
exaclty 6 bytes. Any other number of bytes is OK. But with 6 bytes an additional 0x0D ( 14 ) will be inserted
between my dummy intitilaizing string and the number.
The weird thing is that it doesn't happen where I expected. I walked through every single step that the
stringstream does on its buffer and I see that everything works fine. So it must be the writing to the output file.
But I think it is just a matter of copying some bytes. The output file can not know that there were words and
integers, does it? I also see that the output file is not actually written unless my program returns control to
windows. Now it seems it is a problem not directly related to what kind of stream I use but how I put the
content into a file.
Another question is. Since the stringstream has no constructer to tell the initial buffer size or that takes a
buffer and it has no reserve method, how can I force a initial buffer size to avoid too much copying. For the
case lets say I know the approximate amount of data and just want to make the buffer a little greater.

this is my current listing:
using namespace std;

void f( int i );

void f( int i)
{

}
class CleverStream
{
public:
CleverStream( ostream& str )
{
s = &str;

}
void SaveData( char* sData )
{
// check if position can be set:

//int ip = s->tellp( );

//if( ip == -1 )
// throw exception( "Invalid stream" );

if( s == &cout )
s->seekp( 0 );
unsigned int i = 0;
unsigned int dwBefore = s->tellp( );
s->write( (char*)&i, 4 );// << (char[8])&i; // placeholder int
*s << sData;
unsigned int dwAfter = s->tellp( );
s->seekp( dwBefore );
i = dwAfter - dwBefore;
s->write( (char*)&i, 4 );
// s->flush( );
s->seekp( dwAfter );
}
void Initialize( char* sData )
{
*s << sData;
}

ostream* s;

};
void PutThings( CleverStream& s )
{
s.Initialize( "Initialize" );
s.SaveData( "Khadij" );// 6,
s.SaveData( "Khadija und Ingo machen einen ganz langen Satzg" );
s.SaveData( "S" );
s.SaveData( "Fi" );
s.SaveData( "Dep" );
s.SaveData( "Subj" );
s.SaveData( "Final" );
}

int main( )
{

try
{
// ofstream x( "iotest.txt" );
ofstream x( "iotest.txt", ios_base::out|ios_base::binary );
CleverStream s_file( x );
PutThings( s_file );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
CleverStream s_cout( cout );

PutThings( s_cout );
}
catch ( exception e )
{
cout << e.what( );
}

try
{
cout << endl << endl << endl;
char buf[100];
ostringstream x_str;
ostringstream y_str;
//strstream x_str( buf, 100 );
//strstream y_str( buf, 100 );
//strstream x_str( buf, 100 , ios_base::out|ios_base::binary);
//strstream y_str( buf, 100, ios_base::out|ios_base::binary );

CleverStream s_str( x_str );

PutThings( s_str );

ofstream y( "strtest.txt" );

//y.write( x_str.str( ), x_str.tellp( ) );
y.write( x_str.str( ).c_str(), x_str.str( ).size() );

}
catch ( exception e )
{
cout << e.what( );
}

return 0;
}

Jul 22 '05 #8
Ingo Nolden wrote:
thank you John for your efforts. Indeed it works nearly in any case. Unless the first "counted" output has
exaclty 6 bytes. Any other number of bytes is OK. But with 6 bytes an additional 0x0D ( 14 ) will be inserted
between my dummy intitilaizing string and the number.


0x0D = 13, carriage return. Open the file in binary, not text, mode.

--
Regards,
Buster.
Jul 22 '05 #9
Ok, thank you

that was it. Its my stupid fault, because I had the same thing when I wrote directly to the filestream.

But, I wonder why it happens in a very sppecial case only and when does the stream apply carriage return?
I mean it seemed to be in a operation of copying the whole stream.
Anyway, I am glad to have this solved. Thank you all.

Ingo
Jul 22 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: joesoap | last post by:
Hi can anybody please tell me what is wrong with my ostream operator??? this is the output i get using the 3 attached files. this is the output after i run assignment2 -joesoap #include...
3
by: Victor Irzak | last post by:
Hello, I have an ABC. it supports: ostream & operator << I also have a derived class that supports this operator. How can I call operator << of the base class for derived object??? Is it...
8
by: Boris | last post by:
Is it possible to manipulate the std::ostream to prepend a string when performing output, e.g. // manipute std::cout to prepend "prefix " std::cout << "hallo" << std::endl; // results in...
2
by: Trevor | last post by:
Hello, Please bear with me, I am trying to learn C++. I am implementing some error/debug functions which format a message and output it to a C++ stream. I would like to design it using one low...
4
by: Rock | last post by:
I'm in the process of writing this program for complex numbers and I use DevC++. My professor on the other hand compiles on Borland 5.5. So I ocasionally save and run my work on Borland to see if...
13
by: Peteroid | last post by:
These don't work (I'm using VS C++.NET 2005 Express with clr:/pure syntax): ostream& operator <<( ostream& output, String^ str ) { output << str ; //compile error return output ; } ...
5
by: truce | last post by:
I searched but couldn't find anything _quite_ like this. I have some code I inherited that needs some work. Basically I have a template that is instantiated in the c++ code and so only the...
6
by: Protazy | last post by:
Dear All, I have the following piece of code: --------------------------------------------- void f(const std::ostream &str) { std::ostringstream *pStr = (std::ostringstream*)(&str); std::cout...
4
by: Art Werschulz | last post by:
Hi. I would like one of the constructors for a given class to take an ostream as a parameter. The following example (foo.cc) doesn't work: ...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
0
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.