Home > Net >  save struct into a binary file and read it
save struct into a binary file and read it

Time:05-04

I have array of struct in class,and I want save that in file. if I put the input ac.mem [i] .username except the username is stored in the file And if I put the input ac.mem [i] nothing will be saved. This is part of my code:

const int len=5;
class account {

public:

    struct members {

        string username;
        string password;
        int acsess;

    }mem[len];
};

class account  ac;
....
ac.mem[0] = { "admin","soran",5 };
    ac.mem[1] = { "hamid","hamid",4 };

    fstream acc1("account", ios::binary);
    for (int i = 0; i <= 1; i  ) {

        acc1.write((char*)&ac.mem[i].username, sizeof(ac.mem[i].username));

    }
acc1.close();
....
ifstream acc2("account", ios::binary);
    for (int i = 0; i <= len;   i) {
        acc1.read((char*)&ac.mem[i].username, sizeof(ac.mem[i].username));

        cout << i   1 << "." << setw(10) << ac.mem[i].username << setw(20) << ac.mem[i].password << setw(20) << ac.mem[i].acsess << endl;

    }
    acc2.close();

CodePudding user response:

std::string objects are pretty complex types – they internally maintain pointers to memory. When you just write the internal representation to a file (casting address of to char*) all you write out are these pointers plus possibly some additional management data.

The actual string contents, though, are stored at the locations these pointers point to. When reading back you cannot ever assume to find the same data at the address you've just restored from file (unless the original string object written to still exists – but then playing around with the internals will, if two different std::string objects involved, with 100% probability lead to undefined behaviour due to double deletion, if not reading and writing them from/to memory that way already is).

What you actually want to print to file are the contents of the string – which you get by either std::string::c_str or alternatively std::string::data. You might additionally want to include the terminating null character (hopefully there are no internal ones within the string...) to be able to read back multiple strings, stopping reading each one at exactly the null terminator, then writing to file might look like:

std::string s;   // assign some content...
std::ofstream f; // open some path
if(f)            // stream opened successfully?
{
    f.write(s.c_str(), s.length()   1);
}

Note that std::string::length returns the length without the terminating null character, so if you want/need to include it, you need to add one to as done above.

Alternatively you can write out the string's length first and then skip writing the null character – with the advantage that on reading back you already know in advance how many characters to read and thus to pre-allocate within your objects (std::string::reserve). For compatibilty reasons over different compilers and especially machines make sure to write out fixed-size data types from <cstdint> header, e.g.:

uint32_t length = s.length();
f.write(reinterpret_cast<char const*>(&length), sizeof(length));
f.write(s.c_str(), s.length());

This approach covers internally existing null characters as well (though if such data exists, std::vector<unsigned char> or preferably std::vector<uint8_t> might be better alternative, std::string is intended for texts).

CodePudding user response:

If you want to use C language, you could refer to the following code.

#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable : 4996)
typedef struct {

    char* name;
    int phone;
}address;
int main(void)
{
    int i;
    address a[3];
    for (i = 0; i < 3; i  )
    {
        a[i].name = "jojo";
        a[i].phone = "123456";
    }
        
        FILE* fp;
        fp = fopen("list.txt", "ab"); 
    
        for (i = 0; i < 3; i  )
        {
            printf(" % s, % d",a[i].name,a[i].phone);
            fwrite(&a[i], sizeof(address), 1, fp); 
        }        
        fclose(fp);
    return 0;
}
  • Related