使用流运算符将具有整数值的类保存到二进制文件中 >> /<<

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

本文关键字:gt lt 保存 二进制文件 运算符 整数      更新时间:2023-10-16

我有一个可能很容易的问题。我看到已经类似的问题,但是我尝试的只是对我的情况不起作用。我正在尝试将带有3个不同整数值的类保存到二进制文件中。我需要解决有关超载C 流操作员"&lt;"/">>"。因此,我的实际代码似乎将整数值保存为文件中的二进制值,但是当我尝试从二进制文件中加载它们时,它只会返回一个与原始值不同的整数值。
我的课:

class Time{
public:
    int hour;
    int minute;
    int second;
};

我将单个值保存到文件中的方法。我尝试了使用reinterpret_cast的此操作,例如:( 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;
}

我的代码测试功能的结果是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;
}

希望您能理解我的问题。

@ivaigult所注意到的,您忘记了std ::冲洗 ofstream。为了完成我的答案,我已经通过一些评论修改了您的代码,这很有用。恕我直言,最重要的是避免写诸如:

 os.write(reinterpret_cast<const char *>(&time.hour),sizeof(int));

这是非常危险的,因为如果您在Time 中修改time.hour,则必须记住才能修改sizeof(int)-> sizeof(new type)。如果您忘记了通常会得到内存损坏的错误,这些错误之后却不有趣!使用C 11,您可以使用decltype(time.hour),这给出了:

os.write(reinterpret_cast<const char *>(&time.hour), sizeof(decltype(time.hour)));

不进一步的ADDO是修改后的工作C 11代码,并注释:

#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;
}