2010-10-12 82 views
6

我有一部分内存需要转储到文件。一个原因是将信息保存在某个地方,另一个原因是当我的程序重新启动时再次读取它。将内存转储到文件

这样做的正确方法是什么?

我的第一个想法是:

char* start = my_pointer; 
int i; 
for (i = 0; i < MEMORY_SIZE; i++) { 
    // write *start to file 
    start++; 
} 

我可以写它所有的字符?然后使用这样的东西将其恢复到内存。

//loop 
    *my_pointer = fgetc(f); 
    my_pointer++; 

请问我的“数据结构”生存的“charachters”,或者我需要把它写在某种二进制/六数据模式?或者这是做这件事的一种方法吗?

+4

它是否包含指针? – ruslik 2010-10-12 09:19:50

+0

是的,它包含指针。但我想我可以重新编程一些部分以避免它。感谢所有的答案,它帮助了很多! – kristus 2010-10-12 10:04:38

回答

9

使用字符“b”这个问题被称为“serializing”,可以从琐碎的范围非常复杂。如果您的数据结构是自包含的,例如数组中的一串像素,并且您知道数组维数,则可以将数据转储出来然后再读回数据结构。

如果您的数据中包含例如链接列表或任何类型的指针,那么一旦您读取它们,这些指针就不会指向任何有效的指针。这是更正式的序列化方法开始有意义的地方。

这可以从保存为文件格式,使用数据库,转换为XML或其他分层格式等等。什么是正确的解决方案完全取决于你拥有什么样的数据,以及你正在做什么类型的操作,以及你打算写入然后从磁盘读回的经常。 (。或者,网络或任何你正在做的)

如果你拥有的是数据的一个微不足道的斑点,只是想和你写出来可能最简单的方法,使用fwrite()

fwrite(my_pointer, MEMORY_SIZE, 1, fp); 

和然后fread()读回数据。 也看到一个相关的(或多或少相关取决于你的需求是多么先进)serializing question on StackOverflow

适当的serialization也解决the problems that appear当不同种类的CPU应该能够读取彼此的数据。 C中正确的序列化要比其他语言复杂得多。例如,在Lisp中,所有的数据和代码都已经被序列化了。在Java中,有一些方法可以帮助您序列化数据。C的特性使其成为高性能和系统编程的合适语言,这使得用于其他一些事情更加困难。

+1

我想我要重新编程一下,使它更简单,更容易转储/恢复。 – kristus 2010-10-12 10:07:20

2

如果您使用的是unixy风格的系统,memmap和memcpy可能会为您提供整洁的解决方案。

2

您可以使用

size_t fwrite (const void * ptr, size_t size, size_t count, FILE * stream); 

功能。

ptr - pointer to you memory segment. 
size - size of memory to write. 
stream - file you writing to. 

请问我的“数据结构”生存的“charachters”,或者我需要把它写在某种二进制/六数据模式?或者这是做这件事的一种方法吗?

,当你打开文件 - 在“模式”参数

1

这样做的正确方法是使用序列化库。

您是否真的需要这取决于您的数据的复杂性。如果您需要写出的数据不包含任何类型的指针,那么您可以使用fwrite来写出数据,并使用fread来重新读取数据。只要确保您已打开包含二进制数据的文件模式。

如果序列化数据包含指针,那么使用为此目的而编写的外部库会更好,因为库会确保指针的写入方式可以在稍后进行正确重构。

2

只要您输出的数据中不包含指针,只需将其倾倒出去即可。 (提示:使用可以一次编写长序列数据的调用来减少时间。)唯一需要注意的是,如果要写出整数或浮点数并将它们读回到机器上一个不同的架构(例如,大端而不是小端)。这可能会或可能不会成为您的担忧。

但是,如果你有指针,你有问题。问题是,你不能(很好,不能轻易地)保证你将数据装回到接收进程的虚拟内存空间中的相同位置。更重要的是,如果您的数据有指向您未保存的东西的指针(例如,流浪的FILE*),那么您必须考虑在当时重新合成有效替换的操作。这种序列化是非常重要的,并且需要编写知道你正在保存和加载的代码。

有一种方法可以简化序列化,当您只保存连续数据中的指针并且总是要在同一个体系结构上恢复时。像以前一样抛出内存,但是在其上面至少放置一个前缀描述符,至少指出数据的长度和指针的数量,然后还可以保存(最后)一张确切位置的表格(作为数据中的偏移量)指针是所有数据开始的地方。然后,您可以通过读取数据并执行地址算术来修复所有指针,也就是说,您可以计算出它们指向的原始数据相对于起始位置的偏移量 - 作为char*,而不是原始类型 - 以及确保它们在重新加载后指向相对于整个数据地址的相同偏移量。这是一个有点严重的黑客攻击,并且从表面上看并不是最便携的东西,但是在本段开头提到的限制内,我希望它能够工作。但是,你也会有一个非常便携的序列化格式; 不要指望它在所有任何形式的持续档案使用!