psp1
psp1

Reputation: 537

How to write data from stringstream to a file (CPP)

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.

Upvotes: 2

Views: 7841

Answers (3)

fjardon
fjardon

Reputation: 7996

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;

Upvotes: 0

StevieG
StevieG

Reputation: 8709

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..

Upvotes: 0

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();

Upvotes: 2

Related Questions