Solved

How to get the count of a stringstream

Posted on 2012-04-11
14
3,320 Views
Last Modified: 2012-04-13
I am creating a BINARY string stream that can do both input and output. I want to create a function that would give me the current size in bytes anytime I do an input or/and output when you do a read() or a write().

I have created this small example and I expected the gcount() would do that. But did not.

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int));
  std::cout << "Count " << sstr.gcount() << std::endl;   //Expected 4, but I get 0

  char readString[10];
  sstr.read(readString, sizeof (int));;
  std::cout << "Count " << sstr.gcount() << std::endl;  // This is OK.
   return 0;
}

Any ideas how to do that?
0
Comment
Question by:prain
  • 4
  • 3
  • 3
  • +2
14 Comments
 
LVL 86

Expert Comment

by:jkr
Comment Utility
What about 'sstr.str().size()'?
0
 
LVL 53

Expert Comment

by:Infinity08
Comment Utility
gcount gets the number of characters that were obtained by the last (unformatted) input operation. Doing a write is not an input operation.
0
 

Author Comment

by:prain
Comment Utility
jkr,
Thanks. But what I am expecting is to internal buffer to change when you do a write and a read.

In the following example I am expecting after the two reads, the buffer size() to be 0, because to me read() means "you read out" completely from the buffer.
Seems it's not hapenning in stringstreams. So I was thinking to create my own function to do that.

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int));
  std::cout << "Internal Buffer 1 : " << sstr.str().size() << std::endl;

  sstr.write("12.34", sizeof (float));
  std::cout << "Internal Buffer 2 : " << sstr.str().size() << std::endl;

  char readString[10];
  sstr.read(readString, sizeof (int));;
  std::cout << "Internal Buffer 3 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 4


  sstr.read(readString, sizeof (float));;
  std::cout << "Internal Buffer 4 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 0

 
  return 0;
}
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
Hmmm, your assumptions are wrong for one simple reason:

#include <string>
#include <iostream>
#include <sstream>
 
int main ()
{
  std::stringstream sstr(std::stringstream::in  |  std::stringstream::out | std::stringstream::binary );

  sstr.write("50", sizeof (int)); // writes 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 1 : " << sstr.str().size() << std::endl;

  sstr.write("12.34", sizeof (float)); // writes 4 bytes, since 'sizeof(float) == 4'
  std::cout << "Internal Buffer 2 : " << sstr.str().size() << std::endl;

  char readString[10];
  sstr.read(readString, sizeof (int));; // reads 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 3 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 4


  sstr.read(readString, sizeof (float));; // reads 4 bytes, since 'sizeof(int) == 4'
  std::cout << "Internal Buffer 4 : " << sstr.str().size() << std::endl;
//I am expecting the size() to be 0

 
  return 0;
}

Open in new window


But anyway, 'size()' does not seem to work...
0
 
LVL 53

Accepted Solution

by:
Infinity08 earned 250 total points
Comment Utility
It sounds like you're using the wrong tool for the job.

std::stringstream's are streams, not containers. Getting their size is not relevant for streams.

You can however find out how many bytes can be read from the stream using :

        sstr.rdbuf()->in_avail()

Don't be surprised if it doesn't behave exactly like what you'd expect though, because it does not get the amount of bytes that have been written into the buffer, but rather the amount that are immediately available to be read in the internal buffer (or an estimation if the number of bytes expected to be available of the internal buffer is empty).

For more details, refer to these reference pages :

        http://www.cplusplus.com/reference/iostream/stringstream/rdbuf/
        http://www.cplusplus.com/reference/iostream/streambuf/in_avail/

If this does not do what you want, then a stream is not what you want to use. You might want some kind of circular buffer.
0
 
LVL 32

Expert Comment

by:sarabande
Comment Utility
if you want to write binary data to stringstream do

int i = 50;
ss.write((char*)&i, sizeof(i));

Open in new window


you wouldn't need the binary flag to store binary data cause the binary flag rules only line endings when reading from/writing to files.  

at windows if opening files in text mode a read operation would convert a  CRLF pair in the file  (hex 0x0D 0x0A or '\r' '\n'  in c++) to a single '\n'  in buffer. in a write operation windows would convert '\n' to a CRLF pair in file. as far as i know it has no meaning for stringstream.

stringstream is a typedef of basic_stringstream and is derived from basic_iostream which is derived from both basic_istream and basic_ostream. so actually it is two stream objects though both streams do share a member pointer to basic_streambuf via the common virtual baseclass basic_ios.

              basic_ios
        /                         \
basic_istream     basic_ostream
       \                         /
       basic_iostream
                   |
      basic_stringstream

you could not access the streambuf member of basic_ios directly cause it is a private member, but for my STL the member function rdbuf() would return that pointer.

streambuf has some public member functions like sgetn which returns the count of characters up from a given pointer (pointing into buffer). but all that could be specific to my compiler and its standard library and may not have same implementation at your system.

generally, it seemed easier for me to access the buffer via str() member function as you did. after a write operation the str.size() would show size of the output string buffer. after a read operation (if successful) it should show 0 beside your read operation doesn't read all of the string. so if the ss.str().size() was 10 before read and you read 4 byte, i would expect a rest of 6.

Sara
0
Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

 

Author Comment

by:prain
Comment Utility
It sounds like this is not what I want. But let me tyest out couple of examples and post back here.

BTW, If I use another data structure such as a Queue so something, how would I store "Binary Data". That's for sure is a requirement for us.
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 250 total points
Comment Utility
>> BTW, If I use another data structure such as a Queue so something, how would I store "Binary Data". That's for sure is a requirement for us.

Containers are usually templated, allowing you to store any type of data you want.

You just need to find the right container for your specific needs.
0
 
LVL 53

Assisted Solution

by:Infinity08
Infinity08 earned 250 total points
Comment Utility
Just noticed sarabande's post. While that post is not really relevant for the most part, I wanted to clear up some things to avoid confusion :

>> so actually it is two stream objects though both streams

No it doesn't. That's what virtual inheritance is for.

>> you could not access the streambuf member of basic_ios directly cause it is a private member

No it's not. rdbuf is a public member function.

>> sgetn which returns the count of characters up from a given pointer (pointing into buffer).

No it doesn't. It copies data from the buffer into the provided memory location.
0
 
LVL 32

Expert Comment

by:sarabande
Comment Utility
the basic_ostream and basic_istream part are two objects which share a common basic_ios.

the rdbuf is a member function, the streambuf member is a data member. while the first is public, the second is private (at my system) and could not accessed directly. that is exactly what was told.

the sgetn rightly does a copy. it returns streamsize what made me think it returns the current size of the stream buffer. that is not true. it returns the number of character copied.  

for storing binary and text data usually a std::vector<unsigned char> would be a good choice. you could make an own container class which has the vector as a member and some additional 'pointers' into that buffer. that way the class could behave like a stream if that is the goal. if you want to serialize data for exchange in a network you might consider boost library which has excellent solutions for that.

Sara
0
 
LVL 32

Expert Comment

by:sarabande
Comment Utility
the istream and ostream both add additional members to the shared streambuf which need to be considered cause those determine the interface to the internal buffer. for example, the basic_istream has a member of type streamsize (_Chcount on my system)  which was commented as "character count" and therefore likely is relevant for the question. also in memory there are at least two separated locations where the 'object' was stored. simplification of a complex multi-inheritance class doesn't help avoiding misunderstandings. my understanding of such an object is a graph where each class involved has its own node.

the comment regarding rdbuf was made parallel to the comment of infinity08. it was not intended to add the same information twice. i added the 'obvious' cause oop principles normally would forbid to expose private members by a public getter. i think the rdbuf was provided to allow classes which use a stream class as member to get access to the internal buffer of that stream.

Sara
0
 

Author Comment

by:prain
Comment Utility
evilrix,
Thanks. Yes, I finally got this working the way I want by warapping a stringstream and then having my own counter within the class. The reason I wanted to use a stringstream is because of it's performance. we have done some performance testing on other data structures such as deques, stacks, lists etc and the results of those containers are no where near how stringstream performs specially on a network application. So it was worth for me to warpup a stringstream and build my own class to do the operations I wanted.

Thanks again all.
prain
0
 
LVL 40

Expert Comment

by:evilrix
Comment Utility
Fab. I'm very pleased you found a solution that worked for you. :)
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Article by: SunnyDark
This article's goal is to present you with an easy to use XML wrapper for C++ and also present some interesting techniques that you might use with MS C++. The reason I built this class is to ease the pain of using XML files with C++, since there is…
Having just graduated from college and entered the workforce, I don’t find myself always using the tools and programs I grew accustomed to over the past four years. However, there is one program I continually find myself reverting back to…R.   So …
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

744 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now