简体   繁体   中英

How can I write a struct array in a ".bin" file in c++?

I'm a very inexperienced beginner and I'm in trouble while trying to save some data in a file. My struct looks like this.

struct Appointment {
    wchar_t Name[50]; //name of the patient
    wchar_t Age[3]; //age of the patient
    HWND hwdnd_img; //handler of the image of the patient to  be displayed in windows
    HBITMAP hbitimg; //hbitmap of the image of the patient
    wchar_t wchr_Dirimg[MAX_PATH] = L""; // directory of the image of patient
};

This is an array of the Appointment type I'm trying to write:

Appointment  Arraytosave[5];

Let's say that it has this data:

Arraytosave[0].Name = L"John";   
Arraytosave[0].Age = L"23";
Arraytosave[0].hwdnd_img = example bitmap hwnd;
Arraytosave[0].hbitimg = example hbitmap data;
Arraytosave[0].wchr_Dirimg = L"C:\\Example path";

and here is my code to write it:

void Save(Appointment* Arraytosave, int elements_in_array) {
    wofstream outputF("datos.bin", ios::binary | ios::trunc);
    if (!outputF.is_open()) {
        MessageBox(NULL, L"Cannot open file", L" SAVE_FILE FAILED", MB_ICONERROR);
    }
    else {
        if (!(elements_in_array== 0)) {
            for (int i = 0; i < elements_in_array; i++) {
                int sizeName= sizeof(Arraytosave[i].Name);
                int sizeAge= sizeof(Arraytosave[i].Age);
                int sizehwdnd_img = sizeof(Arraytosave[i].hwdnd_img);
                int sizehbitimg = sizeof(Arraytosave[i].hbitimg);
                int sizewchr_Dirimg = sizeof(Arraytosave[i].wchr_Dirimg);

                outputF.write(reinterpret_cast<wchar_t*>(&Arraytosave[i].Name), sizeName);
                
                outputF.write(reinterpret_cast<wchar_t*>(&Arraytosave[i].Age), sizeAge);
                
                outputF.write(reinterpret_cast<wchar_t*>(&Arraytosave[i].hwdnd_img), sizehwdnd_img );
                outputF.write(reinterpret_cast<wchar_t*>(&Arraytosave[i].hbitimg), sizehbitimg );
                outputF.write(reinterpret_cast<wchar_t*>(&Arraytosave[i].wchr_Dirimg), sizewchr_Dirimg );
            }
            outputF.write(reinterpret_cast<wchar_t*>(elements_in_array), sizeof(int));
            outputF.close();
        }
    }

But when I check the file datos.bin with Notepad, it only displays the Arraytosave[0].Name and nothing else.

John

EDIT

Ok, so I downloaded the "HxD" program and it displays it like this

offset(h) 00 01 02 03 04 05 06 07 08 0A 0B 0C 0D 0E 0F  Decoded text
00000000  4A 6F 68 6E 00                                John.

Firstly, unless you need to pass around pointers or construct arrays on the stack, it's often better to use std::vector<Ty> (where Ty is your array type). A vector is an object and, therefore, also contains a pointer to the end of the used elements and the end of the container. If you need to access an element, you can still use the [] operator and it'll be just as fast (does not do bound checking, similar to an array). This data type is found in the <vector> header.

The next part of your question is saving data of custom types. For this, the Boost library has a serialization function built into it. To use it, #include <boost/archive/text_iarchive.hpp> and #include <boost/archive/text_oarchive.hpp> (after running bootstrap.bat from an elevated CMD window).

Here is a use example: if I am making a game and want to save a player state, I can use Boost to do this as follows

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <fstream>
#include <string>
#include <vector>

class Player
{
private:
    std::string name;
    std::vector<int> lucky_numbers;

public:
    Player(/* Args here */) { /* Stuff here */ }

    friend class boost::serialization::access;  // Required for Boost
    template <typename Archive>  // Template function required
    void serialize(Archive& ar, unsigned version)  // These 2 params required
    {
        // '&' is a Boost overloaded operator for either '<<' or '>>', 
        // depending on the situation
        ar & name;
        ar & lucky_numbers;
    }
};

void save(const Player& player_to_save)
{
    std::ofstream save_filestream(/* rel. path of file */);
    if (save_filestream.is_open())
    {
        // text_oarchive takes std::ofstream as parameter
        boost::archive::text_oarchive save_file(save_filestream);
        save_file << player_to_save;  // Player is serialized into this file
    }
}

void load(Player& player_to_load)
{
    std::ifstream load_filestream(/* rel. path of file */);
    if (load_filesteram.is_open())
    {
        boost::archive::text_iarchive load_file(load_filestream);
        // Below, serialized player is loaded into instance of class
        load_file >> player_to_load;
    }
}

More information on Boost's serialization can be found here . With this method, you have the added benefit of being able to output to any filetype for more operating systems than just Windows (added portability). The information, however, may not be encrypted, so perhaps an encryption/decryption algorithm can wrap around these functions. Hopefully, this helps you at least find a starting place.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM