I'm very new to c++ (and the question is a part of my homework).
I need to store an array of structs in a binary file and read them back. The problem is that my struct contains std::string
field. On the other side I can read the string, but nothing after it. Here is my structure definition:
struct Organization {
int id;
string name;
float paidTaxes;
};
and here is the code where I write array of this struct to a file:
void writeToFile(Organization *orgs, int n) {
ofstream file("orgs.bin", ios::out | ios::binary);
if (!file) { return; }
for (int i = 0; i < n; i++) {
// determine the size of the string
string::size_type sz = orgs[i].name.size();
file.write(reinterpret_cast<char*>(&orgs[i].id), sizeof(int));
// write string size
file.write(reinterpret_cast<char*>(&sz), sizeof(string::size_type));
// and actual string
file.write(orgs[i].name.data(), sizeof(sz));
file.write(reinterpret_cast<char*>(&orgs[i].paidTaxes), sizeof(float));
}
file.close();
}
and here is the code part where I'm reading this file back:
count = 0;
Organization org;
ifstream file;
file.open("orgs.bin", ios::binary);
while (file.good()) {
string::size_type sz;
file.read(reinterpret_cast<char*>(&org.id), sizeof(int));
file.read(reinterpret_cast<char*>(&sz), sizeof(string::size_type));
org.name.resize(sz);
file.read(&org.name[0], sz);
file.read(reinterpret_cast<char*>(&org.paidTaxes), sizeof(float));
count++;
}
As far as I understand, I need to run this loop to determine how many structs are stored in a file. When I run debugger, I successfully read id
field, string size and actual string. However, I never get proper paidTaxes
field (type of float
) and subsequent loops return me junk.
thanks in advance!
The problem is in this line
file.write(orgs[i].name.data(), sizeof(sz));
Here is a typo, insted use
file.write(orgs[i].name.data(), sz);
You shoud write sz bytes, but not sizeof(sz). There is also one more problem with your code. You will read the last record twice, because file.good() will return true after the last record. You can read like that:
while (file.good()) {
string::size_type sz;
if( !file.read(reinterpret_cast<char*>(&org.id), sizeof(int)) )
break;
file.read(reinterpret_cast<char*>(&sz), sizeof(string::size_type));
org.name.resize(sz);
file.read(&org.name[0], sz);
file.read(reinterpret_cast<char*>(&org.paidTaxes), sizeof(float));
count++;
std::cout << org.id << " " << org.name << " " << org.paidTaxes << std::endl;
}