2

I have one function which is an call back from a library it looks like follows:

void onCallBack(int date, const std::stringstream &data); 

I want to write data received from a data variable to an physical file so i am doing this:

void onCallBack(int date, const std::stringstream &data)
{
    ofstream filePtr;
    filePtr.open("data.file", ios::app);

    string dataToWrite = data.str();
    filePtr << dataToWrite.c_str();

    filePtr.close();
}

call back onCallBack function gets called when ever there is an update in data and i want to write this updated data to the file.

problem is that data is std::stringstream type and it behaves like an file/buffer and and from this buffer i just want to read update data part for example:

In first call back data contains string
this is first line

and in second call back it contains:
this is first line
this is second line

In the first call of the call back function I write this is first line string to the file and in second call back I just want to write this is second line to file not the fist line again.

How can i extract only updated part of the std::stringstream.

const std::stringstream &data variable is constant and can't be modified or we can't use tellg or sync.

UPDATE/EDIT:
1. Sorry for c tag.
2. for using read we need to provide block size to read and i don't know the block size.
3. Can you provide an example of doing this using ios_base::xalloc, ios:base::iword, and ios_base::pword.
4. read is not a const but tellg is.
5. yes no one call data.str(""), it is an pure virtual function from lib, in my code i am not doing this.

7
  • 1
    Removed the 'C' tag since this clearly isn't C. Commented Aug 22, 2011 at 12:22
  • 1
    Why not use read instead of str, which, presumably removes the read characters from the buffer. Commented Aug 22, 2011 at 12:23
  • Fixed Grammar mistake in title. Commented Aug 22, 2011 at 12:24
  • 1
    you probably rather want to reset the stringstreams contents than to check for any possible unwritten data. Commented Aug 22, 2011 at 12:24
  • 1
    Does your code ensure no-one will reset the stringstream data, data.str("") etc.? Did you consider inheriting from the string stream buffer, hooking into xsputn, overflow, and/or whatever else may be required? (I haven't checked the details on this, hence no answer.) Commented Aug 22, 2011 at 12:33

3 Answers 3

2

The solution is to remember how much you've read previously and then take only part of the string as appropriate. How you do that is up to you. You could modify your call back to pass some kind of state in:

void onCallBack(int date, const std::stringstream &data, std::string::size_type& state); 

If it's part of an interface (unlikely given what you posted, but that is a good way to do callbacks in general) you can store that state as a private member variable.

If you don't care about being reentrant and the stream never shrinks you could do it as a quick hack using a static variable in this example, which is the easiest to show working here, but asking for trouble:

// What happens if you change the stringstream? 
// This is why you need to re-think the callback interface
static std::string::size_type state = 0;
string dataToWrite = data.str().substr(state);
state += dataToWrite.size();
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the reply, i can't modify the call back prototype and your given solution does not work :(, I have tried adding size_type and substr. after some while 5 to 10 iterations dataToWrite becomes blank.
@psp1: This means that either nothing new is added to the stream, or the stream has shrunk in size (been reset?).
SO what would be the best solution for this, am banging my head on this for last 2 days.
0

You could clear the file contents before writing to it by replacing ios::app with ios::trunc.

Obviously its not optimal to write the entire stream every time, but if you can't change the prototype or flush the stream and you don't know the size of the new data, then I this is the only way I can think of doing it..

1 Comment

No this can not be done, as at the end we are not getting the full file, file will be provided as stack FILO (pipe) to it will repeat only some part of the data.
0

If you are sure the stringstream object is the same for each calls to your callback, you can do that:

filePtr << data.rdbuf() << std::flush;

2 Comments

Welcome to stackoverflow. I've edited your answer to add markup for the code you included.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.