1

I'm trying to record temporal state data. This state data is sent from robot every 8ms. So I want to record complete state data into a file(state.bin).

I want to serialize writing/reading state data to/from a file. And I found that everything is fine with writing.

But when reading from a file, the file is likely to be read over end of file.

I tried while(!in.eof()) and while(in) to check end of file. But both failed.

How do I solve this problem?

Thanks.

Class for serialization

class RobotState
{
public:
   RobotState()
   {

   }

   void printState(std::ostream& stream)
   {
       //Intended for console output
   }

   double time;
   int32_t mode;
   double q[2];
   std::string err_msg;
   friend std::ostream& operator<<( std::ostream& stream, const RobotState& rs );
   friend std::istream& operator>>( std::istream &stream,  RobotState& rs );
};

Serialization/Deserialization

// write to the stream
std::ostream& operator<<( std::ostream &stream,  const RobotState& rs )
{
    stream.write((char*)&rs.time, sizeof(rs.time));
    stream.write((char*)&rs.mode, sizeof(rs.mode));
    stream.write((char*)rs.q, sizeof(rs.q[0])*2);

    //serialize string
    int32_t sz_err_msg = rs.err_msg.size();
    stream.write((char*)&sz_err_msg, sizeof(sz_err_msg));
    stream.write(rs.err_msg.c_str(), sz_err_msg);

    return stream;
}

// read from the stream
std::istream& operator>>( std::istream &stream,  RobotState& rs )
{
    stream.read((char*)&rs.time, sizeof(rs.time));
    stream.read((char*)&rs.mode, sizeof(rs.mode));
    stream.read((char*)rs.q, sizeof(rs.q[0])*2);
    int32_t sz_err_msg; 
    stream.read((char*)&sz_err_msg, sizeof(sz_err_msg));
    char buffer[100];
    stream.read(buffer, sz_err_msg);
    buffer[sz_err_msg] = 0;
    rs.err_msg = buffer;

    return stream;
}

main code

int main(void)
{
   RobotState rs_data;

   /******************Serializing************************/
   std::ofstream out;
   out.open( "robotstate.bin", 
std::ios::out | std::ios::trunc | std::ios::binary );
   //Serialize data with contrived state data
   out.close();

    /******************Deserializing************************/
   std::fstream in;
   in.open("robotstate.bin", std::ios::in | std::ios::binary);
   while(in)
   {
       in >> rs_data;
       rs_data.printState(std::cout);
   }
}
JaeJun LEE
  • 1,234
  • 3
  • 11
  • 27
  • possible duplicate of [Why is “while ( !feof (file) )” always wrong?](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong) – NathanOliver Jul 31 '15 at 17:11
  • Would you mind to bang your question in shape of a [MCVE](http://stackoverflow.com/help/mcve) and post your solution as an answer yourself. That way you edited in your solution for the problem faced in your question, it doesn't fit well the intended Q&A format of StackOverflow. – πάντα ῥεῖ Jul 31 '15 at 17:45
  • Yes, @πάνταῥεῖ. I thought I should show complete code, I mean just copy&paste is enough to compile, when I ask a question. Thanks. And I will answer to my question also. – JaeJun LEE Jul 31 '15 at 17:49
  • @JaeJunLEE THX for your insight! You're the one in about 100reds a day, getting it right. Upvoted just for this little wonder. – πάντα ῥεῖ Jul 31 '15 at 17:53

2 Answers2

2

This might not fix the problem you are seeing, but ...

You should change

while(in)
{
    in >> rs_data;
    rs_data.printState(std::cout);
}

to

while(in >> rs_data)
{
    rs_data.printState(std::cout);
}

That makes sure that you call printState only when the read is successful.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • Thanks. I changed it. – JaeJun LEE Jul 31 '15 at 17:24
  • @JaeJunLEE Did it fix your problem actually? I've' retracted closing your question as duplicate regarding this problem. I'd suspect you may have some problems with buffer reservation and proper NUL (`'\0'`) character appended when reading in `buffer`. – πάντα ῥεῖ Jul 31 '15 at 17:39
  • @πάνταῥεῖ, yes it is solved. It was because when file is about to end, no data was read and `sz_err_msg` variable leaved uninitialized. And actual cause of error was indexing with it(`buffer[sz_err_msg] = 0;`). – JaeJun LEE Jul 31 '15 at 17:45
1

I solved the problem by changing this code

std::istream& operator>>( std::istream &stream,  RobotState& rs )
{
...
    int32_t sz_err_msg;   //Potential cause of error(Uninitialized)
    stream.read((char*)&sz_err_msg, sizeof(sz_err_msg));
    char buffer[100];
    stream.read(buffer, sz_err_msg);
    buffer[sz_err_msg] = 0; //Actual cause of error
...
}

to

std::istream& operator>>( std::istream &stream,  RobotState& rs )
{
...
    int32_t sz_err_msg=0;
    stream.read((char*)&sz_err_msg, sizeof(sz_err_msg));
    char buffer[100];
    stream.read(buffer, sz_err_msg);
    buffer[sz_err_msg] = 0;
...
}

It turned out that uninitialized int32_t variable(sz_err_msg) and indexing with it were the causes. And also my way to use ifstream was wrong as @RSahu pointed.

JaeJun LEE
  • 1,234
  • 3
  • 11
  • 27