Saving objects (C++ string class) to binary files.

Started by
4 comments, last by Baine 21 years, 9 months ago
Howdy all, I was hoping that someone could help me out of a bit of a jam. I''m trying to save a string object, (Created from the string class in C++) to a binary file. But there''s something amiss. Whenever I try to read it back in, the data seems to be missing. I''ve tried using the read/write functions of ifstream and ofstream respectively, but I''m just not sure on where I''m going wrong. If anyone knows of a better method, or can point me to a good tutorial on binary file I/O, then that would be greatly appreciated.. I can''t find a tutorial dealing specifically with this issue though. Thanks for any help Ern
groovy,ern
Advertisement
1. Post your code; it''ll make it possible for us to help you.
2. What you''re trying to do is known as "serialization". Tutorials and references will call it that.


Don''t listen to me. I''ve had too much coffee.
Thanks for the serialization tip Exactly what I was looking for. I usually do post code, when I think it will be helpful. Seeing how this question was more of a theory question, (hehe regardless of how I worded it I''d rather fix my own code, according to the help that you provided. With the serialization thing, I know what to look for now so thanks again

One last question though. I''m trying to save player objects. (ie. they have a string object that contains the name, and various ints for things such as health, strength etc.)

Would it be more efficient to rewrite the code using null-terminated strings as storage for the player name, or continue as I am and incorporate the MFC/Serialization bit. I guess what I''m asking for are pros/cons of String objects vs. standard c-type null terminated strings.

Thanks again for any help.
Ern
groovy,ern
As far as loading/saving strings, I use std::string and
simply store the length in front and then the actual characters.

It''s actually LESS efficient to use null-terminated strings
since you must read the data one byte at a time and check
for NULL, instead of reading in the whole string in one
fell swoop.

MFC? Yuck. Why, oh why?

Also, watch out for Big-Endian vs Little-Endian, if you plan
to port your program to other platforms. If you use only
one platform, then there''s no problem.


~~~~
Kami no Itte ga ore ni zettai naru!
神はサイコロを振らない!
Here is an example, it may not be great but it works :-D


    #include <iostream>#include <fstream>#include <string>using namespace std;class CTest{    // Private class only variables, etc.    private:        int m_iStrlen; // Used to hold the length of the string        string m_strName; // String    // Class Initialization / Uninitialization    public:        CTest(); // Default Class Constructor        ~CTest(); // Class Destructor                // Settings    public:        void SetName(string val); // Sets the name    // Disk Saving/Loading    public:        void Save(string val); // saves the name to a file        void Load(string val); // loads the name from a file    // Information Retrieval    public:        string GetName(void) const; // Get the name};CTest::CTest(){    m_iStrlen = 0;}void CTest::SetName(string val){    m_strName = val;    m_iStrlen = val.length();    return;}void CTest::Save(string val){    // No name set    if (m_strName.length() <= 0 || m_strName.empty())    {        return;        }//if    // open file in output in binary mode    ofstream f(val.c_str(), ios::out | ios::binary);    // failed to open/create file    if (f.fail())    {        return;        }//if    // First save the length of the string    f.write((const char *)&m_iStrlen, sizeof(int));    // Now save the string itself    f.write((const char *)m_strName.begin(), m_iStrlen);    // Close the file, done with it    f.close();    return;}void CTest::Load(string val){    // open file for binary input    ifstream f(val.c_str(), ios::in | ios::binary);    // Failed to open file    if (f.fail())    {        return;        }//if    // First read the string length    f.read((char*)&m_iStrlen, sizeof(int));    // Resize (allocates) m_strName to fit the string to read    m_strName.resize(m_iStrlen);    // Read the string saved into m_strName    f.read((char*)m_strName.begin(), m_iStrlen);    // Close the file, done with it!    f.close();    return;}string CTest::GetName(void) const{    return (m_strName);}CTest::~CTest(){}void SaveTest(CTest &t){        t.SetName("Your name or whatever here");    t.Save("c:\\windows\\desktop\\myname.txt");        return;}void LoadTest(CTest &t){        t.Load("c:\\windows\\desktop\\myname.txt");    cout << myname.GetName() << endl;    return;}int main(){    CTest myname;    SaveTest(myname);    //LoadTest(myname);        return (0);}//main    


[edited by - Shadow Wolf on July 20, 2002 12:42:43 AM]
quote:Original post by Shadow Wolf
f.write((const char *)m_strName.begin(), m_iStrlen);


I wouldn''t do that if I were you. The STL standard does not guarantee that string iterators are char*, nor does it guarantee that the string is a single contiguous memory location. Use this instead:

f.write(m_strName.c_str(), m_iStrlen);

This topic is closed to new replies.

Advertisement