Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Save Class with Integer Values into Binary File with Stream Operator >> / <<

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.

like image 905
Retrogott Avatar asked Aug 22 '26 19:08

Retrogott


1 Answers

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;
}
like image 185
Picaud Vincent Avatar answered Aug 24 '26 09:08

Picaud Vincent



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!