1

I have written two instances ck1,ck2 of a struct named Cookie and have saved them in a binary file named "mydat" by calling a function :

bool s_cookie(Cookie myck,std::string fname) {

std::ofstream ofs(fname,std::ios::binary | std::ios::app);
if(!ofs) return false;

ofs.write((char *) &myck, sizeof(Cookie));

ofs.close();

return true;

}

of course myck can be ck1, ck2, etc, and fname reps the "mydat" binary file. So the two structs have both been saved in the same file. Now I want to read them back into ck3 and ck4 respectively. How do i do that? Cookie looks like this :

struct Cookie {
    std::string name;
    std::string value;
    unsigned short duration;
    bool expired;
};

Thanks

6
  • Can you provide the definition of Cookie? Is it just a POD struct? Commented Oct 13, 2013 at 14:07
  • just added it to the edit check it out Commented Oct 13, 2013 at 14:11
  • 2
    This is the problem. You cannot save a struct like that to a file using binary I/O. Binary I/O does not work on std::string. The reason is that std::string contains internal pointers and pointers cannot be meaningfully saved to file. So you're out of luck you'll have to try another way. The usual way to save a string using binary I/O is first to save the length of the string, and then to save the characters themselves. Then when reading you do the same, read the length of the string, allocate memory for the chars, read the chars. Commented Oct 13, 2013 at 14:19
  • No need to call close unless you actually treat potential errors. Just let the stream close automatically at the end of its scope. Commented Oct 13, 2013 at 14:23
  • If Stack Overflow had a like button, I would have liked john's reply. I just changed the std::string to char [] and it magically worked. Thanks Commented Oct 13, 2013 at 14:35

1 Answer 1

1

Something like writing, but read them, if Cookie is a POD:

std::ifstream ifs(fname,std::ios::binary);

Cookie ck3, ck4;

ifs.read((char *) &ck3, sizeof(Cookie));
ifs.read((char *) &ck4, sizeof(Cookie));

Also, you should check the result of each opening and reading operation and handle them.


Update: After your update and seeing the Cookie, you can not simply write it into a file. You should serialize it or make a well-defined protocol to read/write data.

A simple workaround is (read the comment):

// Assume name and value are not longer that 99
// and you don't care about wasted space in the file

struct CookiePOD {

    CookiePOD(const Cookie &p)
    {
      // I ignored bound checking !
      std::copy(p.name.begin(), p.name.end(), name);
      name[p.name.size()] = 0;

      std::copy(p.value.begin(), p.value.end(), value);
      value[p.value.size()] = 0;

      duration = p.duration;
      expired = p.expired;
    }  

    char name[100];
    char value[100];
    unsigned short duration;
    bool expired;
};

And then try to read/write CookiePOD instead of Cookie.

Sign up to request clarification or add additional context in comments.

5 Comments

Unfortunately this doesn't work because the OP struct is not POD, (I know this was posted before he updated his question).
Thanks it works but if now run the program. The program terminates. I'm working on Windows and the program stops execution at runtime. More help
@BarbelZeusBryo What you are trying will not work. See the comment I made on your question. M M. gave this answer before he knew what was in your struct.
@john Yep, just changed the std::string to char [] and it worked. Thanks a lot john
@john: I just saw the structure of Cookie, you're right. Reading OPS's code for writing data I assumed it is a POD. Now, I have to edit the answer.

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.