istringstream question | | |
Hi,
My question is regarding std::istringstream. I am serializing data to
an ostringstream and the resulting buffer turns out just fine.
But, when I try the reverse, when the istringstream encounters the two
byte shorts, it either thinks it has reached the null terminator? or
eof and consequently stops reading values back in. It doesn't matter
whether or not I use the std::ios::binary flag when opening the
istringstream or the readsome method which does in-fact, not report
eof. It still can't build the shorts back up.
Any suggestions would be appreciated. Here is a brief example:
#include <cstring>
#include <sstream>
int
main(int argc, char** argv)
{
typedef unsigned short uint;
char* key = new char[8];
strncpy (key, "the key", 7)[7] = '\0';
uint var1 = 'a';
uint var2 = 'b';
std::ostringstream os;
os.write(key, 8);
os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
std::cout << "stream string: " << os.str() << std::endl;
std::cout << "stream c_str: " << os.str().c_str() << std::endl;
char* keytwo = new char[8];
keytwo[7] = 0;
uint feedme1 = 0;
uint feedme2 = 0;
//
// Here is where my question lies - how to initialize istringstream?
//
std::istringstream is (os.str().c_str(), std::ios::binary);
is.read(keytwo, 8);
std::cout << "\n\nkeytwo: " << keytwo << std::endl;
if (is.eof())
{
std::cout << "END OF FILE!!!" << std::endl;
}
is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
std::cout << "feedme1: " << feedme1 << std::endl;
is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
std::cout << "feedme2: " << feedme2 << std::endl;
//
// but it is clear the both shorts are present in the c_str
//
for (int i = 0; i < 12; ++i)
{
std::cout << os.str().c_str()[i] << std::endl;
}
//
// and my favorite way to see what's happening
//
for (int i = 0; i < 12; ++i)
{
std::cout << (int)os.str().c_str()[i] << std::endl;
}
delete [] key;
delete [] keytwo;
return 0;
}
Thanks,
-Luther | | | | re: istringstream question
"Luther Baker" <lutherbaker@yahoo.com> wrote...[color=blue]
> My question is regarding std::istringstream. I am serializing data to
> an ostringstream and the resulting buffer turns out just fine.
>
> But, when I try the reverse, when the istringstream encounters the two
> byte shorts, it either thinks it has reached the null terminator? or
> eof and consequently stops reading values back in. It doesn't matter
> whether or not I use the std::ios::binary flag when opening the
> istringstream or the readsome method which does in-fact, not report
> eof. It still can't build the shorts back up.
>
> Any suggestions would be appreciated. Here is a brief example:
>
>
> #include <cstring>
> #include <sstream>
>
> int
> main(int argc, char** argv)
> {
> typedef unsigned short uint;
>
> char* key = new char[8];
> strncpy (key, "the key", 7)[7] = '\0';
> uint var1 = 'a';
> uint var2 = 'b';
>
> std::ostringstream os;
> os.write(key, 8);
> os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> std::cout << "stream string: " << os.str() << std::endl;
> std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>
> char* keytwo = new char[8];
> keytwo[7] = 0;
> uint feedme1 = 0;
> uint feedme2 = 0;
>
> //
> // Here is where my question lies - how to initialize istringstream?
> //
> std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
As soon as you use .c_str() here, you lose everything after the first
zero character, which becomes the terminator. You need to use the
string directly:
std::istringstream is(os.str(), std::ios::binary);
HTH
[color=blue]
> is.read(keytwo, 8);
> std::cout << "\n\nkeytwo: " << keytwo << std::endl;
> if (is.eof())
> {
> std::cout << "END OF FILE!!!" << std::endl;
> }
>
> is.read(reinterpret_cast<char*>(&feedme1), sizeof(feedme1));
> std::cout << "feedme1: " << feedme1 << std::endl;
>
> is.read(reinterpret_cast<char*>(&feedme2), sizeof(feedme2));
> std::cout << "feedme2: " << feedme2 << std::endl;
>
> //
> // but it is clear the both shorts are present in the c_str
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << os.str().c_str()[i] << std::endl;
> }
>
> //
> // and my favorite way to see what's happening
> //
> for (int i = 0; i < 12; ++i)
> {
> std::cout << (int)os.str().c_str()[i] << std::endl;
> }
>
> delete [] key;
> delete [] keytwo;
>
> return 0;
> }
>
>
>
> Thanks,
>
> -Luther[/color] | | | | re: istringstream question
Victor Bazarov wrote:
[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote...
>[color=green]
>>My question is regarding std::istringstream. I am serializing data to
>>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
....[color=blue][color=green]
>>std::ostringstream os;
>>os.write(key, 8);
>>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
>>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
>>std::cout << "stream string: " << os.str() << std::endl;
>>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
>>
>>char* keytwo = new char[8];
>>keytwo[7] = 0;
>>uint feedme1 = 0;
>>uint feedme2 = 0;
>>
>> //
>> // Here is where my question lies - how to initialize istringstream?
>> //
>>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
>
>
> As soon as you use .c_str() here, you lose everything after the first
> zero character, which becomes the terminator. You need to use the
> string directly:
>
> std::istringstream is(os.str(), std::ios::binary);[/color]
Ah.
So - for my real project, I have the following:
void AnObject::DeSerialize(const void* buffer)
{
std::istringstream ( ? ... );
....
}
Following your lead, I'll try to create a string.
std::string str(reinterpret_cast<const char*>(buffer));
Nope. Loses the tail end ... (NULL terminated)
const int size = X;
std::string str(size, size)
for (int i = 1; i < size; ++i)
{
str[i] = buffer[i];
}
Ah ... that works! And I do, in fact, know exactly how many bytes I need
to copy.
Would you suggest a smoother way or different approach now that you see
a bit more of what I'm after?
Thanks,
-Luther | | | | re: istringstream question
"Luther Baker" <lutherbaker@yahoo.com> wrote...[color=blue]
> Victor Bazarov wrote:
>[color=green]
> > "Luther Baker" <lutherbaker@yahoo.com> wrote...
> >[color=darkred]
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
> ...[color=green][color=darkred]
> >>std::ostringstream os;
> >>os.write(key, 8);
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize[/color][/color][/color]
istringstream?[color=blue][color=green][color=darkred]
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);[/color]
>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject::DeSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }[/color]
Don't you mean
std::string str(buffer, size);
?
[color=blue]
>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?[/color]
I am not sure what way would be "smoother". If you need to have meaningful
zeroes in the "buffer", then you cannot hope to call deserialise without
passing the size of the stream in, btw.
void AnObject::Deserialize(const char *buffer)
{
std::istringstream is(std::string(buffer, size), ios::binary);
// now read from it
}
Victor | | | | re: istringstream question
"Luther Baker" <lutherbaker@yahoo.com> wrote in message
news:2h7rgrF9uacdU1@uni-berlin.de...[color=blue]
> Victor Bazarov wrote:
>[color=green]
> > "Luther Baker" <lutherbaker@yahoo.com> wrote...
> >[color=darkred]
> >>My question is regarding std::istringstream. I am serializing data to
> >>an ostringstream and the resulting buffer turns out just fine.[/color][/color]
> ...[color=green][color=darkred]
> >>std::ostringstream os;
> >>os.write(key, 8);
> >>os.write(reinterpret_cast<const char*>(&var1), sizeof(var1));
> >>os.write(reinterpret_cast<const char*>(&var2), sizeof(var2));
> >>std::cout << "stream string: " << os.str() << std::endl;
> >>std::cout << "stream c_str: " << os.str().c_str() << std::endl;
> >>
> >>char* keytwo = new char[8];
> >>keytwo[7] = 0;
> >>uint feedme1 = 0;
> >>uint feedme2 = 0;
> >>
> >> //
> >> // Here is where my question lies - how to initialize[/color][/color][/color]
istringstream?[color=blue][color=green][color=darkred]
> >> //
> >>std::istringstream is (os.str().c_str(), std::ios::binary);[/color]
> >
> >
> > As soon as you use .c_str() here, you lose everything after the first
> > zero character, which becomes the terminator. You need to use the
> > string directly:
> >
> > std::istringstream is(os.str(), std::ios::binary);[/color]
>
> Ah.
>
> So - for my real project, I have the following:
>
> void AnObject::DeSerialize(const void* buffer)
> {
> std::istringstream ( ? ... );
> ....
> }
>
> Following your lead, I'll try to create a string.
>
> std::string str(reinterpret_cast<const char*>(buffer));
>
> Nope. Loses the tail end ... (NULL terminated)
>
> const int size = X;
> std::string str(size, size)
> for (int i = 1; i < size; ++i)
> {
> str[i] = buffer[i];
> }
>
> Ah ... that works! And I do, in fact, know exactly how many bytes I need
> to copy.
>
> Would you suggest a smoother way or different approach now that you see
> a bit more of what I'm after?[/color]
const char *p = static_cast<const char *>buffer;
std::string str(p, p + X);
-Mike | | | | re: istringstream question
Victor Bazarov wrote:[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote...
>[/color]
....[color=blue][color=green]
>> const int size = X;
>> std::string str(size, size)
>> for (int i = 1; i < size; ++i)
>> {
>> str[i] = buffer[i];
>> }[/color]
>
>
> Don't you mean
>
> std::string str(buffer, size);[/color]
....[color=blue]
>
> I am not sure what way would be "smoother". If you need to have meaningful
> zeroes in the "buffer", then you cannot hope to call deserialise without
> passing the size of the stream in, btw.
>
> void AnObject::Deserialize(const char *buffer)
> {
> std::istringstream is(std::string(buffer, size), ios::binary);
> // now read from it
> }
>[/color]
For some reason, I thought that *std::string str(buffer, size);* would
have strncpy semantics and stop copying buffer at the first null. But as
I'm sure you're aware, it doesn't.
When I said "smoother" I guess I meant more elegant. It seems clunky to
have to create a std::string to get a std::istringstream interface over
the buffer - but I guess it is a *string* stream.
Many Thanks,
-Luther | | | | re: istringstream question
Mike Wahler wrote:
[color=blue]
> "Luther Baker" <lutherbaker@yahoo.com> wrote in message
> news:2h7rgrF9uacdU1@uni-berlin.de...[/color]
....[color=blue][color=green]
>>
>>Would you suggest a smoother way or different approach now that you see
>>a bit more of what I'm after?[/color]
>
>
> const char *p = static_cast<const char *>buffer;
> std::string str(p, p + X);[/color]
Does that imply
string::string (const char* cstrBegin, const char* cstrEnd);
Josuttis pg.509 left that one out! unless that is silently turned into
string::string (InputIterator beg, InputIterator end);
Thanks for your insight,
-Luther | | | | re: istringstream question
>[color=blue]
> When I said "smoother" I guess I meant more elegant. It seems clunky to
> have to create a std::string to get a std::istringstream interface over
> the buffer - but I guess it is a *string* stream.
>[/color]
Use an istrstream instead. Reading from a fixed size buffer is about the
only reasonable use of strstream.
john |  | | | | /bytes/about
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 226,449 network members.
|