所以我一直在c ++中使用紧凑数据类型,从内存中保存或从文件中加载只需要复制内存中的一些内存。
然而,明显的缺点是,如果你需要在数据上添加/删除元素,它就会变得混乱。版本控制也存在问题,假设您分发使用数据版本A的程序,然后第二天您制作版本B,然后再版本C。
我想这可以通过使用像xml或json这样的东西来解决。但是假设你出于技术原因不能这样做。
最好的方法是做什么,除了必须做出不同的情况等(这可能是非常丑陋的,我想象)
答案 0 :(得分:2)
来自3dsmax的想法(如果我记得很清楚):将文件分成块,每个块都有一个描述它的标题(可能很长)和长度。如果您不知道标题,则在阅读时通过了解len跳到下一个标题。此过程在每个块中递归应用,并确保后向兼容性。
答案 1 :(得分:2)
我不知道您的'技术原因'是什么,但如果它们涉及速度或数据大小,那么我可能会建议Protocol Buffers作为您的解决方案。它明确地设计用于处理版本控制。它会比简单地转储一个结构稍微慢一点,但只是稍微一点,而且它会更便携并且更好地处理版本控制。
答案 2 :(得分:0)
这就是 I 会破解它的方式。这是一种“hacky”方法,但可以扩展到更复杂。
struct file
{
int32 fileversion; //different parsers, one for each file version
int offsetlen; //length of blocks
int numblocks; //number of blocks
int* fileoffsets; //this array has internal offsets, corresponding to blocks
block* blocklist; //blocks.
};
struct block
{
//stuff here of a fixed length
};
要使用固定大小的块编写文件,算法将是这样的 -
write(f.fileversion)
write(f.offsetlen)
write(f.numblocks)
for i in f.blocklist
write(f.blocklist[i])
并阅读 -
f.fileversion = read(sizeof(f.fileversion))
f.offsetlen = read(sizeof(f.offsetlen))
f.numblocks = read(sizeof(f.numblocks))
for i in f.numblocks
f.blocks[i] = read(f.offsetlen)
对于异质块,您需要在阅读时跟踪偏移量。
答案 3 :(得分:0)
如果您采用“以列为导向”的方式,则可以根据需要添加字段。
用旧方式原始结构:
struct Person {
string name;
int age;
};
vector<Person> People; // single file for all fields
用旧方式添加字段:
struct Person {
string name;
int age;
string address; // now must rewrite files on disk
};
新的改进方式:
namespace People {
vector<string> name; // first file
vector<int> age; // second file
}
添加新方式:
namespace People {
vector<string> name;
vector<int> age;
vector<string> address; // add a third file and leave other two alone
}
要点是每个字段都是自己的文件。额外的好处是用户只需要读/写他想要的字段,因此版本控制变得更容易。
答案 4 :(得分:0)
我们在工作中处理这个问题。这不是最好的,但有些事情可以做:
为所有文件添加标题,第一个字段为“version”,第二个字段为“length”。在加载时,您现在可以适当地处理旧版本。
如果可以,请将规则“永不删除数据字段,始终在文件末尾添加字段”。如果你这样做,那么你的加载代码可以加载一个旧的,更短版本的文件,只需将可用数据读入结构中,并保留最后的字段(不在文件中)初始化。当你开始使用结构数组时,这就会崩溃,此时你需要手动加载数据。