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

write user-defined structure to file, in binary mode

本文关键字:结构 文件 定义 二进制 模式 用户      更新时间:2023-10-16

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)。也许我对课本的理解有误……或者代码有问题?

但是生成的文件不能被文本编辑器读取

那是因为您没有在文件中写入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));
// ...

这里有一个bug。正如您从文档中看到的,ostream::write写入它的关联流缓冲区。直到调用ostream::flush,缓冲区才被写入输出。因此,在上面的代码中,文件在读取时为空。这显然可以通过在读取文件之前调用out.flush()来修复。

正如在注释中提到的,这是完全不可移植的。这意味着您的程序在一台计算机上编写的文件可能无法被另一台计算机上的程序读取。即使在同一台计算机上,使用不同编译器选项编译的两个程序也可能没有相同的类内存布局。

为什么不按标准的方式去做呢?简单易懂

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();
}