i have a probably pretty easy question.I saw already similiar question like this but all I tried doesn't work for my case. I'm trying to save a class with 3 different Integer Values into a binary file. I need to solve this about overloading the C++ stream Operator "<<"/ ">>". So my actual Code seems to save the Integer Values as binary in my file but when i try to load them back from my binary file it just returns me a integer value that is not the same like the original value.
My Class:
class Time{
public:
int hour;
int minute;
int second;
};
My Method to Save the Single Values to the File. I tried this one with the reinterpret_cast and without for example :(char*) $time.hour
std::ostream& operator<<(std::ostream &os, Time &time){
os.write(reinterpret_cast<const char *>(&time.hour),sizeof(int));
os.write(reinterpret_cast<const char *>(&time.minute),sizeof(int));
os.write(reinterpret_cast<const char *>(&time.second),sizeof(int));
return os;
}
std::istream& operator >>(std::istream &is,Time &time){
is.read((char*)&time.hour,sizeof(int));
is.read((char*)&time.minute,sizeof(int));
is.read((char*)&time.second,sizeof(int));
return is;
}
My Code to test the function the result for this is 1878006928 :
int main() {
Time time;
time.hour = 24;
time.minute = 33;
time.second = 10;
std::ofstream os("test.txt", std::ios::binary | std::ios::out);
os << time;
Time time2;
std::ifstream is("test.txt",std::ios::binary | std::ios::in);
is >> time2;
std::cout << time2.hour;
}
Hope you can understand my problem.
As noticed by @ivaigult you forgot to std::flush your ofstream.
To complete my answer I have modified your code with some comments, that can be useful. IMHO the most important thing is to avoid to write things like:
os.write(reinterpret_cast<const char *>(&time.hour),sizeof(int));
This is very dangerous because if you modify time.hour in your Time you have to remember to also modify sizeof(int) -> sizeof(new type). If you forget that you typically get memory corruption bugs that are not funny to found afterward! With C++11 you can use decltype(time.hour), this gives: like:
os.write(reinterpret_cast<const char *>(&time.hour), sizeof(decltype(time.hour)));
Without further addo here is the modified working c++11 code with comments:
#include <fstream>
#include <iostream>
class Time
{
public:
int hour;
int minute;
int second;
// *** would allow you to access protected members (if any)
//
friend std::ostream &operator<<(std::ostream &os, Time &time);
friend std::istream &operator>>(std::istream &is, Time &time);
};
std::ostream &operator<<(std::ostream &os, Time &time)
{
// *** sizeof(in) -> sizeof(decltype(time.hour)
// otherwise bug prone: if you modify the Time class, you have to remember to
// modify this function too!
os.write(reinterpret_cast<const char *>(&time.hour), sizeof(decltype(time.hour)));
os.write(reinterpret_cast<const char *>(&time.minute), sizeof(decltype(time.minute)));
os.write(reinterpret_cast<const char *>(&time.second), sizeof(decltype(time.second)));
return os;
}
std::istream &operator>>(std::istream &is, Time &time)
{
// *** ditto: bug prone
// + be consistent: if you use reinterpret_cast before, use it also here
// and not the C-style cast(char *)
is.read(reinterpret_cast<char *>(&time.hour), sizeof(decltype(time.hour)));
is.read(reinterpret_cast<char *>(&time.minute), sizeof(decltype(time.minute)));
is.read(reinterpret_cast<char *>(&time.second), sizeof(decltype(time.second)));
return is;
}
int main()
{
Time time;
time.hour = 24;
time.minute = 33;
time.second = 10;
// *** std::ios::binary is enough, std::ios::out is redundant with
// std::_o_fstream
std::ofstream os("test.txt", std::ios::binary);
os << time;
// os.close(); or at least a flush
os.flush();
Time time2;
// *** ditto: std::ios::binary is enough
std::ifstream is("test.txt", std::ios::binary);
is >> time2;
std::cout << time2.hour << " " << time2.minute << " " << time2.second;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With