c++从二进制文件读取/写入类
c++ Read/Write class from/to binary file
我需要将一个类写入一个二进制文件,然后我需要读取它。
我有Triangle
和BinaryFile
类,还有一些其他类。我不确定我是写错了还是读错了。读取时出错。调试后,我认为它为我的私有变量获取了不合适的数据。如果有人能就如何使其正常工作给我一些建议,我将非常高兴。
我不确定是否应该粘贴整个代码,所以我会给你一小段代码。以防万一,这里有我的源代码的下载链接:
https://my.pcloud.com/publink/show?code=XZJ7CYZbsLWLglqV5p83csijcEUTFqqpM3k
我是一个编程新手,英语说得不太好,所以我提前为我的错误道歉。
class Point
{
private:
int x;
int y;
};
class Figure
{
private:
string name;
string type;
};
class Triangle: public Figure
{
private:
Point p1, p2, p3;
};
class BinaryFile
{
private:
string FileName;
fstream File;
public:
//...
void AddNewFigure(istream& stream)
{
File.open(this->FileName, ios::binary | ios::app);
if(!this->File)
{
cerr<<"File error <"<<this->FileName<<">n";
exit(1);
}
Triangle fig;
fig.MakeNewFigure(stream);
File.write((char*)&fig, sizeof(Triangle));
File.close();
}
Triangle GetTriangle()
{
Triangle trig;
Point p;
string str(""); int x(0);
File.open(this->FileName, ios::binary | ios::in);
if(!this->File)
{
cerr<<"File error <"<<this->FileName<<">n";
exit(1);
}
File.read((char*)&trig, sizeof(Triangle));
File.close();
return trig;
}
};
答案取决于您这样做是为了了解文件的工作方式,还是保存到文件只是偶然的,您不在乎它是如何工作的。
如果你只想保存和恢复这些东西,而不在乎它是如何工作的,那么就使用第三方库。他们有很多。
如果你想学习如何在文件中读写东西,那么你需要制作自己的读写功能。我制作了一个示例程序来解释它是如何工作的:
#include <string>
#include <fstream>
#include <iostream>
class Point
{
private:
int x;
int y;
public:
Point():x(0),y(0){}
Point(int x,int y):x(x),y(y){}
void write(std::ostream& f)
{
// We can just write out the bytes for x and y because
// they are primitive types stored in the class
f.write( (char*)&x, sizeof(x) );
f.write( (char*)&y, sizeof(y) );
}
void read(std::istream& f)
{
// We can just read the bytes directly into x and y because
// they are primitive types stored in the class
f.read( (char*)&x, sizeof(x) );
f.read( (char*)&y, sizeof(y) );
}
};
class Figure
{
private:
std::string name;
std::string type;
public:
Figure(){}
Figure(std::string name,std::string type):name(name),type(type){}
void write(std::ostream& f)
{
size_t size;
// we need to store the data from the string along with the size
// because to restore it we need to temporarily read it somewhere
// before storing it in the std::string (istream::read() doesn't
// read directly to std::string)
size = name.size();
f.write( (char*)&size, sizeof(size_t) );
f.write( (char*)name.c_str(), size );
size = type.size();
f.write( (char*)&size, sizeof(size_t) );
f.write( (char*)type.c_str(), size );
}
void read(std::istream& f)
{
size_t size;
char *data;
// when we read the string data we need somewhere to store it
// because we std::string isn't a primitive type. So we read
// the size, allocate an array, read the data into the array,
// load the std::string, and delete the array
f.read( (char*)&size, sizeof(size) );
data = new char[size+1];
f.read( data, size );
data[size]=' ';
name = data;
delete data;
f.read( (char*)&size, sizeof(size) );
data = new char[size+1];
f.read( data, size );
data[size]=' ';
type = data;
delete data;
}
};
class Triangle: public Figure
{
private:
Point p1, p2, p3;
public:
Triangle(){}
Triangle(Point x,Point y,Point z,Figure f):p1(x),p2(y),p3(z),Figure(f){}
void write(std::ostream& f)
{
// First write the base class then write the members of this class
Figure::write(f);
p1.write(f);
p2.write(f);
p3.write(f);
}
void read(std::istream& f)
{
// First read the base class then read the members of this class
Figure::read(f);
p1.read(f);
p2.read(f);
p3.read(f);
}
};
class BinaryFile
{
private:
std::string FileName;
std::fstream File;
public:
BinaryFile(std::string FileName) : FileName(FileName) {};
void WriteTriangle()
{
File.open(FileName, std::ios::binary | std::ios::out);
if(!File)
{
std::cerr<<"File error <"<<FileName<<">n";
exit(1);
}
Triangle trig({1,2},{3,4},{5,6},{"name","type"}); // something new
trig.write(File);
File.close();
}
Triangle ReadTriangle()
{
File.open(FileName, std::ios::binary | std::ios::in);
if(!File)
{
std::cerr<<"File error <"<<FileName<<">n";
exit(1);
}
Triangle trig; // default values
trig.read(File);
File.close();
return trig;
}
};
main()
{
BinaryFile bin("file.bin");
bin.WriteTriangle();
Triangle trig = bin.ReadTriangle();
// at this point trig has the values we stored
return 0;
}
由于您的源代码很大并且缺少数据文件,因此不容易重现错误。但快速检查显示,您可以使用区块操作读取和写入二进制数据:
Triangle trig;
...
File.read((char*)&trig, sizeof(Triangle));
不幸的是,这种方法只有在您想要保存/加载的对象属于可复制的类时才有效,如下代码所示:
if (is_trivially_copyable<Triangle>::value)
cout << "Triangle is trivially copyable" << endl;
else cout << "Triangle is not trivially copyable" << endl;
因此,您必须逐个字段序列化对象内容写入,而不是使用bloc操作。这个关于序列化的常见问题解答应该可以帮助您考虑替代方案。
您想要的是序列化应该保存到文件中的类/数据。有几个库已经针对时间和内存消耗进行了优化。你介意使用第三方图书馆吗?
如果没有,可以看看例如boost序列化、谷物,甚至谷歌的ProtoBuf。如果你使用C++11,我认为谷物是一个好的开始。
如果您想编写自己的序列化,则必须考虑对于每个具有动态大小(如字符串)的对象,还需要将对象的大小保存到文件中。有关更多信息,请查看此处:
https://stackoverflow.com/a/11003590/5874704
- 正在读取二进制文件(is_open)
- 读取二进制文件并解释为整数
- 读取二进制文件直到结束 c++
- 如何在标准c ++中流式传输/读取二进制文件的中间部分并写入另一个文件?
- 读取二进制文件的惯用C++17标准方法是什么
- 从末尾读取二进制文件
- C++逐个字符读取二进制文件字符
- 读取二进制文件大小的短自上周以来停止工作
- 读取二进制文件时出现问题
- 读取二进制文件时如何输出?
- C++:如何在线程中读取二进制文件并将其写入另一个线程?
- 在C 中读取二进制文件会返回意外值
- 尝试读取二进制文件会清除文件本身
- C 读取二进制文件
- 通过C 读取二进制文件的问题
- ifstream读取二进制文件在发行模式下工作,但在调试模式下不使用
- 分段 追加和读取二进制文件时出错
- 使用C++中的MsgPack读取二进制文件
- 有没有一种优雅的方法来读取二进制文件并将其内容复制到向量<int>
- 如何读取二进制文件并在屏幕上打印 3?