以二进制模式将用户定义的结构写入文件

时间:2015-09-09 07:55:35

标签: c++ file-io

c++教科书中,我了解到我应该能够做到这一点(在二进制模式下将用户定义的类型写入/读取到文件中):

struct mystruct
{
    int a;
    double b;
};

void main()
{
    struct mystruct s = {1,2.0};
    std::ofstream out("binary.dat", std::ios::out | std::ios::binary);
    out.write(reinterpret_cast< const char* > (&s), sizeof(struct mystruct));
}

代码编译并运行但文本编辑器无法读取生成的文件。然后我用二进制模式读取文件:

std::ifstream in("binary.dat", std::ios::in | std::ios::binary);
struct mystruct t;
in.read( reinterpret_cast<char*> (&t), sizeof(struct mystruct));

然而事实证明它不成功(它没有获得数字1和2.0)。也许我错误地解释了教科书......,或者代码可能有问题?

2 个答案:

答案 0 :(得分:2)

  

但是文本编辑器无法读取生成的文件

那是因为您没有将 text 写入文件。在任何字符编码中都无法有意义地解释数据。您可以使用hexdump或类似工具进行有意义的表示。

  

也许我错误地解释了教科书......或者代码可能有问题?

我不这么认为。除了奇怪的格式和冗余关键字之外,单独的代码片段没有任何问题。当然还有文件的不可移植性。以及main的无效返回类型。

但是,你所做的可能是这样的单一程序:

// ...
std::ofstream out("binary.dat", std::ios::binary);
out.write(reinterpret_cast<const char*>(&s), sizeof(s));
std::ifstream in("binary.dat", std::ios::binary);
in.read(reinterpret_cast<char*>(&t), sizeof(t));
// ...

这里有一个错误。从文档中可以看出,ostream::write写入了它的关联流缓冲区。直到ostream::flush被调用才将缓冲区写入输出。因此,在上面的代码中,文件在读取时是空的。显然可以通过在读取文件之前调用out.flush()来解决这个问题。

正如评论中所提到的,这根本不是便携式的。这意味着您的程序在一台计算机上编写的文件可能无法被另一台计算机上的程序读取。即使在同一台计算机上,使用不同编译器选项编译的两个程序也可能没有相同的内存布局。

答案 1 :(得分:2)

为什么不采用标准方式。它简单易懂

struct mystruct {
    int a;
    double b;

    friend std::ostream & operator <<(std::ostream & out, mystruct & mys) {
        out << mys.a << " " << mys.b << std::endl;
        return out;
    }

    friend std::istream & operator >>(std::istream & in, mystruct & mys) {
        in >> mys.a >> mys.b;
        return in;
    }
};

现在用法很简单。例如

mystruct s;

阅读

std::ifstream in("binary.dat");
in >> s;

std::ofstream out("binary.dat");
out << s;

如果要序列化

,还可以在结构中重载std::string运算符
operator std::string() const {
   std::stringstream ss;
   ss << a << " " << b;
   return ss.str();
}