Thread: how can i save a structure on a file?

  1. #1
    Registered User
    Join Date
    Aug 2013
    Posts
    451

    how can i save a structure on a file?

    i have these 2 functions for write and read from a structure variable on a file:
    Code:
    //save a structure object to a file
    template<typename structure>
    void SaveDataBase(string filename,structure *StructureVariable )
    {
        remove(filename.c_str());
        ofstream output_file(filename.c_str(), ios::binary);
        output_file.write(reinterpret_cast<char*>(StructureVariable), sizeof(structure));
    
        output_file.close();
    }
    
    //read a structure object from a file
    template<typename structure>
    void ReadDataBase(string filename,structure *StructureVariable )
    {
        ifstream input_file(filename.c_str(), ios::binary);
        input_file.read(reinterpret_cast<char*>(StructureVariable), sizeof(structure));
        input_file.close();
    }
    they seem to work. i get results. but when i end the program the process is open for a while.
    i was testing that 2 functions 1 by 1 and i have seen that i have a problem on ReadDataBase():
    Code:
    input_file.read(reinterpret_cast<char*>(StructureVariable), sizeof(structure));
    because, using just the SaveDataBase(), the program ends normaly.
    can anyone explain to me what is wrong?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    There's the issue that structure must be a standard layout type, and then you'll have to consider that pointer members could pose a problem.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User MutantJohn's Avatar
    Join Date
    Feb 2013
    Posts
    2,665
    Can't you just use `static_cast` for pointer to pointer conversions? I'm assuming that the value of the pointer itself will still be valid even with a by-value cast.

  4. #4
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    MutantJohn: error: invalid static_cast from type 'user*' to type 'char*'.
    laserlight : what you mean by that?
    heres the structure:
    Code:
    struct user
    {
        string name;
        int age;
        image foto;
    };
    
    user usrName;
    user usrName2;
    //how i use:
    usrName.age=23;
                usrName.foto.FileName="007.gif";
                usrName.name="joaquim miguel";
                SaveDataBase("username1.dat",&usrName);
                ReadDataBase("username1.dat",&usrName2);
                mnuExitSys2.imgMenu =usrName2.foto;
                mnuExitSys2.Caption=usrName2.name;

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    No you can't just write that struct to a file.

    Standard C++ - serialisation



    > string name;
    This is an object, where the actual character string is stored somewhere else in memory. All you have in name is a pointer and some other data like the current and maximum sizes.

    You have to recursively traverse your objects inside the 'struct user'
    Eg
    Code:
    size_t len = StructureVariable->name.length();
    output_file.write(reinterpret_cast<char*>(&len), sizeof(len));
    output_file.write(reinterpret_cast<char*>(StructureVariable->name.c_str()), len);
    output_file.write(reinterpret_cast<char*>(&StructureVariable->age), sizeof(StructureVariable->age));
    // ditto for image
    Reading would be something like
    Code:
    size_t len;
    input_file.read(reinterpret_cast<char*>(&len), sizeof(len));
    char *temp = new char[len];
    input_file.read(temp, len);
    StructureVariable->name = string(temp,len);
    delete [] temp;
    input_file.read(reinterpret_cast<char*>(&StructureVariable->age), sizeof(StructureVariable->age));
    // ditto for image
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by joaquim
    what you mean by that?
    Basically, you cannot just reinterpret_cast a pointer to an object to a pointer to char, write out the bytes, and then read the bytes back in, reinterpret_cast to a pointer to the object's type, and always expect it to work. There are conditions under which this will work, and if these conditions are not met, it may not work.

    Consider this structure:
    Code:
    struct X
    {
        int* p;
    };
    If you write out the bytes of an X object, you will write out a pointer's value, i.e., an address. This is the address of an int object that exists in a given context. When you read the bytes back in, you get the same pointer's value, but is this address still the address of the int object that existed when the bytes were written out? This is a possible problem with std::string, since std::string should have a pointer member at some level of its implementation. As such, you should write out the content of the std::string instead, whether as text or in some special serialisation format.

    Even if there are no pointer members involved, another consideration is whether the type satisfies the requirements for standard layout type. I don't know if this is likely to be an issue if you are running the same program for reading and writing, but in general it is an issue, so the image type is a concern as it might not meet the requirements for a standard layout type (or run into problems with pointer members).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    I would really suggest you use a serialising library, such as cereal, to handle writing and reading structures from disk. It handles all the difficult stuff behind your back, making it trivial do this.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    i'm sorry, but can i overloading the output_file.Write() operator\function, for work for strings and the image?

  9. #9
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    What do you not understand from the forum where you marked this topic as resolved?

    Everything that has been said here seems like a rehash of the information you received in that topic.

    Jim

  10. #10
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    jimblumberg : i understand what you said. but i 'losed'.. sorry. anotherthing: i can't enter on that link
    laserlight : i'm sorry, but using 'try'(never used these code before), can i 'ignore' that error? why ask!?! because that 2 functions give me the results that i need. the big problem is when i close\end the application(takes some seconds for end it)

  11. #11
    Registered User
    Join Date
    May 2010
    Posts
    4,633
    i understand what you said
    No you don't.

    If you did you would stop all the serial cross-posting.


    Jim

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by joaquim
    but using 'try'(never used these code before), can i 'ignore' that error?
    This is a terrible way to learn to program. Before making this stab-in-the-dark proposal, you should have read up on the try and catch keywords, and in so doing acquired some understanding of exceptions. In the process, you would have used the try keyword in your experimentation, and you would have also thrown an exception without try/catch to see what happens. You would then be in a better position to understand what you are asking about.

    Quote Originally Posted by joaquim
    because that 2 functions give me the results that i need. the big problem is when i close\end the application(takes some seconds for end it)
    Multiple people have explained to you that your approach is problematic, yet you insist that it works. Maybe you got "lucky", but not quite as lucky as you want because you have anomalous behaviour anyway. You have been suggested the use of the cereal library, so look into it.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    finally i can get the actual\1st frame... but i need all frames(animated gif):
    Code:
    friend std::ostream& operator << (std::ostream& lhs, image& rhs)
        {
    
            //Create an empty IStream:
            IStream* pIStream = nullptr;
            if(CreateStreamOnHGlobal(NULL, TRUE, (LPSTREAM*)&pIStream)!=S_OK)
                DebugText("error on creating an empty IStream");
    
            //choose image format for save it on IStream:
            // Get encoder class id for jpg compression
            // for other compressions use
            //    image/bmp
            //    image/jpeg
            //    image/gif
            //    image/tiff
            //    image/png
            CLSID pngClsid;
            GetEncoderClsid(L"image/tiff", &pngClsid);
    
            // Setup encoder parameters
            EncoderParameters *encoderParameters=(EncoderParameters*)malloc(sizeof(EncoderParameters));
            encoderParameters->Count = 1;
            encoderParameters->Parameter[0].Guid = EncoderSaveFlag;
            encoderParameters->Parameter[0].Type = EncoderParameterValueTypeLong;
            encoderParameters->Parameter[0].NumberOfValues = 1;
            // setup compression level
            ULONG parameterValue = 50;
            encoderParameters->Parameter[0].Value = &parameterValue;
    
            //  Save the 1st frame to the stream
            parameterValue = EncoderValueMultiFrame;
            Status            stat;
            if(rhs.img->Save(pIStream, &pngClsid, encoderParameters) != Ok)
            {
                pIStream->Release();
                MessageBox("error on saving to IStream");
            }
    
            //stop the animation:
            rhs.tmrAnimation.Stop();
    
            //save all frame on stream:
            for(int i=1; i<rhs.framecount; i++)
            {
    
                //select the frame for be saved:
                UINT count = 0;
                count = rhs.img->GetFrameDimensionsCount();
                vector<GUID> pDimensionIDs;
                pDimensionIDs.resize(count);
                rhs.img->GetFrameDimensionsList(pDimensionIDs.data(), pDimensionIDs.size());
                rhs.img->SelectActiveFrame(&pDimensionIDs[0],i);
    
                //save the frame on stream:
                parameterValue = EncoderValueFrameDimensionPage;
                stat=rhs.img->Save(pIStream,&pngClsid, encoderParameters);
    
                //select the actual frame for the timer animation:
                if(i==rhs.framecount-1)
                    rhs.img->SelectActiveFrame(&pDimensionIDs[0],rhs.intSelectFrame);
    
                //testing if was saved:
                if(stat == Ok)
                    DebugText("Page " + to_string(i) + " saved successfully.");
                else
                    DebugText("Page " + to_string(i) + " not saved successfully.\t" + to_string(stat));
            }
    
            //closing stream:
            parameterValue = EncoderValueFlush;
            stat=rhs.img->SaveAdd(encoderParameters);
            if(stat != Ok)
                DebugText("Page not saved successfully:  " + to_string(GetLastError()) + "   "  + to_string(stat) );
    
            //continue the timer:
            if(rhs.framecount>0)
                rhs.tmrAnimation.Start();
    
            //getting the stream size:
            STATSTG sts;
            pIStream->Stat(&sts, STATFLAG_DEFAULT);
            ULARGE_INTEGER uli = sts.cbSize;
            LARGE_INTEGER zero;
            zero.QuadPart = 0;
            int size = (int)uli.QuadPart;
    
            //save the stream to char*
            char* bits = new char[size];
            DebugText("write: " + to_string(size));
            ULONG written;
            pIStream->Seek(zero, STREAM_SEEK_SET, NULL);
            pIStream->Read(bits, size, &written);
    
            //write the stream size on file
            lhs.write(reinterpret_cast<char*>(&size),sizeof(int));
    
            //write pBuff data on file
            lhs.write(reinterpret_cast<char*>(bits),size);
    
            //clean resources
            delete[] bits;
            pIStream->Release();
            free(encoderParameters);
            return lhs;
        }
    see the 'for' give me a positive output, so the frame seems to be saved on stream.
    but when i need close the stream:
    Code:
    //closing stream:
            parameterValue = EncoderValueFlush;
            stat=rhs.img->SaveAdd(encoderParameters);
            if(stat != Ok)
                DebugText("Page not saved successfully:  " + to_string(GetLastError()) + "   "  + to_string(stat) );
    - the GetLastError() give me zero;
    - the stat give me 7. so it's a win32 error(from stat enum).
    what i'm doing wrong for save all frames on stream?

  14. #14
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    What does error 7 mean? What does the doc say?
    I'd also try simplifying the program. Make it as dumb as possible and make sure it works, then go from there.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  15. #15
    Registered User
    Join Date
    Aug 2013
    Posts
    451
    Status enumeration (Windows)

    7 - Win32Error: Indicates that the method generated a Win32 error.

    the msdn have 1 sample, but they use it in a diferent way. they aren't explaint for gif correctly
    Image.Save(IStream*, const CLSID*, const EncoderParameters*) method (Windows)

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. how save a structure object on a file and read it?
    By joaquim in forum C++ Programming
    Replies: 39
    Last Post: 09-27-2015, 02:14 PM
  2. Replies: 0
    Last Post: 03-21-2013, 03:31 PM
  3. Open File/Save File crashes on cancel?
    By Blackroot in forum Windows Programming
    Replies: 0
    Last Post: 08-02-2008, 02:16 AM
  4. How to save into file ?
    By Th3-SeA in forum C Programming
    Replies: 7
    Last Post: 11-15-2003, 06:54 PM
  5. Save to File
    By Korhedron in forum C++ Programming
    Replies: 19
    Last Post: 12-01-2002, 05:16 PM

Tags for this Thread