将内存转储到文件

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

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

我的第一个想法是:

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”一样存在,还是需要以某种二进制/ hexa数据模式编写? 或者这是一种标准的做法吗?

这个问题被称为“ 序列化 ”,可以从简单到复杂。 如果您的数据结构是自包含的,例如数组中的一堆像素,并且您知道数组维度,则可以将数据转储出来然后将其读回。

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

这可以是保存为文件格式,使用数据库,转换为XML或其他分层格式等。 什么是OK解决方案完全取决于您拥有什么类型的数据,以及您在其上执行的操作类型以及您计划从磁盘写入和读取的频率 。 (或者网络。或者你在做什么。)

如果您拥有的是一小部分数据,并且您只想以最简单的方式编写它,请使用fwrite() :

 fwrite(my_pointer, MEMORY_SIZE, 1, fp); 

然后使用fread()来读取数据。 另请参阅StackOverflow上的相关(或多或少相关,具体取决于您的需求有多高级) 序列化问题 。

正确的序列化还解决了当不同类型的CPU应该能够彼此读取数据时出现的问题 。 C语言中的正确序列化比其他语言复杂得多。 例如,在Lisp中,所有数据和代码都已经序列化。 在Java中,有一些方法可以帮助您序列化数据。 使C语言成为高性能和系统编程的合适语言的C属性也使其更难以用于其他一些事情。

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

您可以使用

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

function。

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

我的“数据结构”是否会像“charachters”一样存在,还是需要以某种二进制/ hexa数据模式编写? 或者这是一种标准的做法吗?

当你打开文件时 – 在“模式”参数中使用’b’字符

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

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

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

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

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

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