管理基于内存的数据格式的更改

时间:2011-01-11 17:38:34

标签: c++ data-structures file-format

所以我一直在c ++中使用紧凑数据类型,从内存中保存或从文件中加载只需要复制内存中的一些内存。

然而,明显的缺点是,如果你需要在数据上添加/删除元素,它就会变得混乱。版本控制也存在问题,假设您分发使用数据版本A的程序,然后第二天您制作版本B,然后再版本C。

我想这可以通过使用像xml或json这样的东西来解决。但是假设你出于技术原因不能这样做。

最好的方法是做什么,除了必须做出不同的情况等(这可能是非常丑陋的,我想象)

5 个答案:

答案 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”。在加载时,您现在可以适当地处理旧版本。

  • 如果可以,请将规则“永不删除数据字段,始终在文件末尾添加字段”。如果你这样做,那么你的加载代码可以加载一个旧的,更短版本的文件,只需将可用数据读入结构中,并保留最后的字段(不在文件中)初始化。当你开始使用结构数组时,这就会崩溃,此时你需要手动加载数据。