【发布时间】: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*)&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.txt 和s.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*)&s, sizeof(S));-- 这行不通 -- 想想看。如果std::string中有一千个字符,sizeof(S)仍然是,我不知道,也许是几个字节。那么,当您仅指定要写入的 48 个字节时,将使用什么魔法将这数千个字符写入文件?然后将使用什么魔法将文件中的这 48 个字节转换为 1000 个字符的字符串?