【问题标题】:How to create an object using bytes read from a binary file in C++? [duplicate]如何使用从 C++ 中的二进制文件读取的字节创建对象? [复制]
【发布时间】:2021-04-10 17:10:36
【问题描述】:

假设有一个 C++ 结构 S,其中一个实例被创建并写入二进制文件。然后将所述文件读回到程序中,并应从中创建一个实例。第二部分是如何实现的?

这里是S的定义:

struct S {
    int value;
    string txt;
};

现在要使用此类结构的数据创建一个二进制文件,使用以下函数:

int writeStructAsBinary() {
    ofstream ofs;

    S s;
    s.txt = "Hello World";
    s.value = 10;

    ofs.open("output.dat", ios::out | ios::binary);
    if (!ofs.good()) { cerr << "Error opening file." << endl; return 1; }
    ofs.write((char*)&s, sizeof(S));
    ofs.close();
    return 0;
}

我有点不确定(char*)&amp;s 是否正确,但这就是我得到的。

现在如何将output.dat 文件中的数据读回程序中?原则上它应该只是“读取 sizeof(S) 字节”,但是如何从字节创建结构?这是我的尝试?

int readAndPrintBinary() {
    ifstream ifs;
    ifs.open("output.dat", ios::in | ios::binary);
    if (!ifs) { cerr << "Could not open file." << endl; return 1; }
    
    
    ifs.seekg(0, ios::beg);
    char* binaryInstance = new char[sizeof(S)];
    ifs.read(binaryInstance, sizeof(S));
    ifs.close();
    
    delete binaryInstance;
    return 0;
}

我现在想确认s.txts.value。我该怎么做?

主程序是这样的:

#include <iostream>
#include <string>
#include <sstream>
#include <string>
#include <fstream>

using namespace std;

int main() {
    writeStructAsBinary();
    readAndPrintBinary();
}

使用reinterpret_cast 重新创建对象:

int readAndPrintBinary() {
    ifstream ifs;
    ifs.open("output.dat", ios::in | ios::binary);
    if (!ifs) { cerr << "Could not open file." << endl; return 1; }
    
    ifs.seekg(0, ios::beg);
    char* binaryInstance = new char[sizeof(S)];
    ifs.read(binaryInstance, sizeof(S));
    S* s = reinterpret_cast<S*>(binaryInstance);
    ifs.close();
    
    cout << "s->txt = " << s->txt << endl;
    cout << "s->value = " << s->value << endl;

    delete[] binaryInstance;
    return 0;
}

【问题讨论】:

  • 这段代码永远不会像显示的那样工作,因为你不能以这种方式序列化std::string成员。
  • 除非你有 POC 类型,否则这不太可能工作。可以肯定的是,它不适用于 std::string 成员。
  • 您需要定义用于在文件中存储数据的格式。文件是字节流——除非您定义某种方式将数据表示为字节流,否则您无法在文件中读取和写入数据。不能保证计算机已经将数据存储为字节流,并且在大多数情况下不会。
  • 我将更改示例以仅包含 int 和 char 数组。那应该使它成为 POD,对吗?
  • @TMOTTM ofs.write((char*)&amp;s, sizeof(S)); -- 这行不通 -- 想想看。如果std::string 中有一千个字符,sizeof(S) 仍然是,我不知道,也许是几个字节。那么,当您仅指定要写入的 48 个字节时,将使用什么魔法将这数千个字符写入文件?然后将使用什么魔法将文件中的这 48 个字节转换为 1000 个字符的字符串?

标签: c++ io


【解决方案1】:

如果S 有一个非 POD 类型的成员,则不能执行此操作,它确实:std::string。它会调用未定义的行为,并且几乎肯定会崩溃。

如果 S 是 POD 类型,您可以通过以下方式重新创建对象:

S *s = reinterpret_cast<S*>(binaryInstance);

然后你必须确保你永远不会删除s,而只调用delete[] binaryInstance;

请记住,结构也可能有填充,因此您可能会写出一堆无用的填充字节(在最坏的情况下,它们可能包含堆中的垃圾,这可能会导致您的程序的安全隐患!!)

您更安全的选择是直接将S 的成员一个一个地持久化。是的,它的代码更多,但更安全、更便携。

【讨论】:

    猜你喜欢
    • 2011-12-05
    • 1970-01-01
    • 2022-01-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-11
    • 1970-01-01
    相关资源
    最近更新 更多