[英]Storing, retrieving binary data or bytes to and from a file for a std::deque?
我正在为游戏编写“重播系统”,并且想知道如何存储记录的帧?
至于现在,我有以下代码/结构(请注意:此代码已缩短):
struct Point4D { float x, y, z, w; };
struct Point3D { float x, y, z; };
struct Point2D { float x, y; };
struct QuatRot { Point4D Front,Right,Up; };
struct VehicleInfo
{
Point3D Pos,Velocity,TurnSpeed;
QuatRot Rotation;
};
namespace Recorder
{
struct FrameInfo
//~380 bytes / frame| max 45600 bytes @ 120 fps
//max 3.7 GB raw data for 24 hours of recording, not bad..
{
std::chrono::high_resolution_clock::duration time;
VehicleInfo Vehicle;
int Nitro;
float RPM;
int CurrentGear;
};
std::deque<FrameInfo> frames;
FrameInfo g_Temp;
void ProcessRecord()
{
//record vehicle data here to g_Temp
frames.push_back(g_Temp);
return;
}
//other recording code.......
};
我在想的是,制作一个字节的原始数组,将其分配给双端队列容器的大小,使用memcpy将它们从双端队列复制到数组,然后将所有数组字节写入文件。
然后,如果我想读取记录数据,我只需读取文件的字节并将其分配给新数组,然后使用memcpy将数组内容复制到双端队列。
这很像.. C.方式吗? 必须采用其他方法将数据存储在文件中,然后将其读回双端队列(也许使用某些C ++ 11功能?)。
我将如何完成?
您推荐哪种方法?
如果这很重要,我正在使用Windows。
memcpy
是过早的优化。
从磁盘读取内容时,瓶颈是磁盘IO,而不是将其从内存的一部分复制到另一部分。
修复您的数据结构,使其使用固定大小的数据结构(而不是int
,使用32位int等)。
不要以二进制形式编写std::chrono::high_resolution_clock::duration
库更新可以完全改变大小,而无需眨眼或流泪,更不用说它的含义了。 用ms
或其他形式写出,因此含义始终保持不变(以64位整数表示)。 然后,您可以将其读回到std::chrono::high_resolution_clock::duration
。
序列化时,请务必写出版本号和结构大小,以便反序列化甚至可以处理基本的版本控制。
我会写一个“到流”和“从流”。 “流式”写出版本号和大小。 “从流”读取版本号和大小,加载当前版本和流版本中的每个字段,清除剩余的,然后从流中读取剩余的数据。
如果发现需要更高的性能,您会注意到,汽车的位置和角度的变化比齿轮的变化要频繁得多。 另外,丢弃在现有帧之间合理插值的帧会大大减小重放格式的大小(根据您的描述,这并不意味着您正在重放中运行物理)。 最后,如果您具有一致的物理模型,则只能存储用户输入并基于此输入进行重放(但这很难实现)。
其他缺点:只需在有问题的结构上调用operator=
即可替换SRECORDASSIGN。 像0x4C
这样的魔术数字应用于指针都是很愚蠢的,并且几乎总是可以用简单的结构成员访问来替换。
如果我正确地解释了您的问题(很累,那么如果我错了,请发表评论),您想在文件之间来回记录。
可以使用任何结构轻松完成此操作:
struct Foo
{
float bar;
int baz;
};
std::ostream& operator<<(std::ostream& stream, const Foo &foo)
{
stream << foo.bar << " " << foo.baz;
}
std::ofstream& operator<<(std::ofstream& stream, Foo &foo)
{
stream.write(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
stream.write(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}
std::ifstream& operator>>(std::ifstream& stream, Foo &foo)
{
stream.read(reinterpret_cast<char*>(&foo.bar), sizeof(bar));
stream.read(reinterpret_cast<char*>(&foo.baz), sizeof(baz));
}
您可以使用
#include <fstream>
#include <iostream>
int main()
{
Foo foo;
foo.bar = -1.2f;
foo.baz = 37;
std::cout << foo << "\n";
std::ofstream output;
output.open("myfile", std::ios::binary);
output << foo;
output.close();
std::ifstream input;
input.open("myfile", std::ios::binary);
input >> foo;
input.close();
std::cout << foo << "\n";
}
有关std::basic_ostream::write
和std::basic::istream::read
,建议您访问cppreference.com。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.