2010-10-12 19 views
6

Tengo una parte de mi memoria que quiero volcar en un archivo. Una de las razones es guardar la información en alguna parte, y otra es leerla nuevamente cuando mi programa se reinicie.Volcado de memoria en el archivo

¿Cuál es la forma correcta de hacerlo?

Mi primer pensamiento fue:

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

¿Puedo escribirlo todo como personajes? Y luego use algo como esto para restaurarlo a la memoria.

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

¿Mis "estructuras de datos" sobrevivir como "charachters", o tengo que escribirlo en algún tipo de datos en modo/hexa binaria? ¿O es una forma estándar de hacer esto?

+4

¿Contiene punteros? – ruslik

+0

Sí, contiene punteros. Pero creo que puedo reprogramar algunas partes para evitarlo. Gracias por todas las respuestas, ¡ayudó mucho! – kristus

Respuesta

9

Este problema se llama "serializing" y puede ir desde triviales a realmente complicado. Si su estructura de datos es independiente, por ejemplo, un montón de píxeles en una matriz y conoce las dimensiones de la matriz, puede simplemente volcar los datos y luego volver a leerlos.

Si tiene, por ejemplo, listas vinculadas, o punteros de cualquier tipo, en sus datos, esos punteros no señalarán nada válido una vez que los haya leído. Aquí es donde un enfoque más formal a la serialización comienza a tener sentido.

Esto puede abarcar desde guardar como formatos de archivo, usar bases de datos, convertir a XML u otro formato jerárquico, y así sucesivamente. Lo que es una solución correcta depende completamente del tipo de datos que tenga y de qué tipo de operaciones esté haciendo, además de cómo a menudo planea escribir y luego volver a leer desde el disco. (.. O red, o lo que está haciendo)

Si lo que tienes es una mancha trivial de datos, y lo que desea es escribir de la manera más sencilla posible, utilice fwrite():

fwrite(my_pointer, MEMORY_SIZE, 1, fp); 

y luego fread() para leer los datos. También vea un relacionado (más o menos relacionado dependiendo de cuán avanzadas sean sus necesidades) serializing question on StackOverflow.

Propia serialization también resuelve the problems that appear cuando se supone que diferentes tipos de CPU pueden leer datos entre sí. La serialización adecuada en C es mucho más complicada que en otros lenguajes. En Lisp, por ejemplo, todos los datos y el código ya están serializados. En Java, existen métodos para ayudarlo a serializar sus datos.Las propiedades de C que lo convierten en un lenguaje adecuado para el alto rendimiento y la programación de sistemas también lo hace más difícil de usar para otras cosas.

+1

Creo que voy a volver a programar un poco para que sea más simple y fácil de volcar/restaurar. – kristus

2

Si tienes un sistema de estilo unixy, memmap y memcpy pueden darte una buena solución.

2

Puede utilizar

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

función.

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

¿Mis "estructuras de datos" sobrevivir como "charachters", o tengo que escribirlo en algún tipo de datos en modo/hexa binaria? ¿O es una forma estándar de hacer esto?

que abre archivo - utilizar el carácter 'b' en el "modo" PARAM

1

La forma correcta de hacerlo es utilizar una biblioteca de serialización.

si realmente es necesario que depende de la complejidad de los datos. Si los datos que necesita para escribir no contiene punteros de cualquier tipo, a continuación, sólo podría utilizar fwrite para escribir los datos y fread para leerlo de nuevo. Sólo asegúrese de que usted ha abierto el archivo con los datos en binario modo.

Si los datos a serializar contienen punteros, es mucho mejor utilizar una biblioteca externa escrita para este fin, ya que la biblioteca se asegurará de que los punteros se escriban de forma que puedan reconstruirse correctamente más adelante.

2

Mientras los datos que se están deshaciendo a cabo no contiene punteros, simplemente deshacerse de ellos de esa manera va a funcionar. (SUGERENCIA: utilice las llamadas que pueden escribir largas secuencias de datos, todo de una vez, para reducir el tiempo). Lo único a lo que hay que tener cuidado es escribir números enteros o números en coma flotante y leerlos en una máquina con una arquitectura diferente (por ejemplo, big endian en lugar de little endian). Eso podría o no ser una preocupación para ti.

Pero si usted tiene punteros dentro, tienes un problema. El problema es que no se puede (y no se puede) garantizar fácilmente que se carguen los datos en la misma posición en el espacio de la memoria virtual del proceso de recepción. Además, si tiene datos que apuntan a cosas que no está guardando (por ejemplo, un callejero FILE*), entonces debe pensar en qué hacer para resintetizar un reemplazo válido en ese momento. Tal serialización es profundamente no trivial, y requiere escribir código que tenga conocimiento de lo que está guardando y cargando exactamente.

Hay una forma de simplificar un poco la serialización cuando solo se tienen punteros dentro de los datos contiguos que se guardan y siempre se restaurarán en la misma arquitectura. Deseche la memoria como antes, pero coloque un descriptor de prefijo que diga al menos la longitud de los datos y el número de punteros dentro, luego también guarde (al final) una tabla de exactamente dónde (como desplazamientos dentro de los datos) el los punteros son y donde estaba el inicio de todos los datos. A continuación, puede restaurar leyendo los datos y realizando la aritmética de direcciones para corregir todos los punteros, es decir, puede calcular qué desplazamiento se relaciona con el inicio de los datos originales a los que apuntaban (como char*, no el tipo original) y asegúrese de que apuntan a la misma compensación relativa a la dirección de los datos completos después de volver a cargar. Este es un truco bastante burdo y formalmente no es lo más portátil que haya existido, pero dentro de las restricciones delineadas al principio de este párrafo, espero que funcione. Sin embargo, también tendrá un formato de serialización realmente no portátil; no cuente con él en absoluto para cualquier tipo de uso de archivo persistente!

Cuestiones relacionadas