Estructuras de escritura y lectura (fwrite – fread) con punteros

5 minutos de lectura

avatar de usuario
usuario1111399

Estoy trabajando en un proyecto de buzón y tengo estas dos estructuras:

estructura mmbox_mail

struct mmbox_mail {
  char *sender, *recipient; 
  char *obj, *date;
  char flags; 
  size_t size; 
};

y

correo_t

typedef struct{
  struct mmbox_mail info;
  void *body;
  void *next;
} mail_t;

No puedo modificar los campos de las estructuras, porque necesito datos variables (para este propósito usé char* en lugar de char[]).

Cada estructura mail_t es un correo. Necesito guardar todos los correos de un usuario en un archivo, que puede ser un archivo binario o de texto (pero creo que es mejor con un archivo binario, porque tengo la void* cuerpo que es difícil de guardar en texto sin formato.

Intenté hacer esto, pero parece que no funciona:

while(mailtmp != NULL){
  fwrite(mailtmp, sizeof(mail_t), 1, fp);

  /* next mail */
  mailtmp=mailtmp->next;
}
while(mailtmp != NULL){  /* i have a list of mails and i use a mailtmp pointer to save each mail */

¿Usted me podría ayudar? Traté de buscar por todas partes pero nunca encontré a alguien que pidiera guardar dos estructuras, una dentro de la otra.

Por supuesto, eso no funcionará ya que para las cadenas copiará el tamaño del puntero (generalmente 4 bytes). Veo 3 opciones aquí:

  1. Serialización de datos, archivo binario (http://en.wikipedia.org/wiki/Serialization).
  2. Creación de un formato para almacenar datos en un archivo de texto.
  3. Use lenguaje de marcado como XML/JSON, etc.

En cualquier caso, deberá revisar todos los campos de la estructura para poder escribirlos en el archivo de datos. En cuanto a la lectura, en los primeros 2 casos, tendría que leer exactamente en el orden en que escribió los datos, en el tercer caso, podría leer los campos de forma independiente en cualquier orden.

En caso de que elija el primer método, para cada campo de cadena (char *) escriba también un byte de terminación cero para que siempre sepa dónde termina cuando lo vuelve a leer.

  • Ok, no puedo usar XML/JSON, etc. porque no lo sé 🙁 Intenté crear un formato para almacenar datos (como guardar el remitente, luego guardar el destinatario y luego guardar los datos, etc.) pero no parece muy eficiente.. (se acepta cualquier sugerencia.. 🙂 ) Por cierto, buscaré la serialización.. 🙂

    – usuario1111399

    22 de diciembre de 2011 a las 9:55


  • La idea de serializar datos es que escriba las partes exactamente en el mismo orden en que las leyó. Entonces, por ejemplo, si necesita almacenar clientes con nombre, edad, dirección, abriría el archivo y, aunque no EOF: escribir nombre (con byte de terminación cero), escribir edad (entero, 4 bytes), escribir dirección (con cero- byte de terminación). La lectura sería: abrir archivo, mientras no EOF: leer caracteres hasta cero caracteres en el búfer (nombre), leer 4 bytes (edad), leer caracteres hasta cero caracteres en el búfer (dirección).

    – dimir

    22 de diciembre de 2011 a las 10:08

  • Está bien. Lo tengo. Hoy vuelvo a escribir esa rutina y los mantengo en contacto. 😀 (realmente lo siento por mi mal inglés… 🙁 ) ¡Muchas gracias! 😀

    – usuario1111399

    22 de diciembre de 2011 a las 13:33


  • Discusión anterior sobre las posibilidades de serialización aquí: stackoverflow.com/questions/371371/…

    – dimir

    22 de diciembre de 2011 a las 13:51

  • Además, si está familiarizado con SQL, ¿consideraría usar libsqlite? Especialmente si hay muchos datos.

    – dimir

    22 de diciembre de 2011 a las 13:57


avatar de usuario
Kaslai

Lo que está haciendo es guardar la representación binaria literal de mail_t en el archivo de texto, que es solo un montón de punteros. Lo que quieres hacer es algo en el sentido de:

fprintf( fp, "To: %s\nFrom: %s\n....\nContents: %*s\n\n", mailtmp->info.recipient, mailtmp->info.sender, mailtmp->info.size, mailtmp->body );

Eso representará los valores señalados como una cadena y los guardará en el archivo. Un puntero a una ubicación en la memoria que tiene su aplicación es un poco inútil para la mayoría de las personas después de que dicha aplicación se cierra;)

EDITAR: “¿Podría ayudarme? Traté de buscar en todas partes, pero nunca encontré a alguien que pidiera guardar dos estructuras, una dentro de la otra”.

Si solo tuviera tipos de datos de primera clase, como ints o floats, etc., su método funcionaría perfectamente. Sin embargo, dado que está utilizando tipos de segunda clase, es decir, sus matrices char y void, debe especificar cómo se deben guardar los datos señalados.

  • Lo intenté de esta manera, pero un problema que encontré es: ¿cómo guardar en texto sin formato el *cuerpo vacío? Quiero decir, el cuerpo del correo electrónico puede contener todo tipo de datos, por lo que no puedo guardarlo como texto sin formato… ¿o no? oh

    – usuario1111399

    22 de diciembre de 2011 a las 9:47


  • Bueno, el formato de correo electrónico es intrínsecamente texto sin formato. Los archivos binarios adjuntos a un correo electrónico se basan en 64 para permitir la transferencia a través del protocolo de texto sin formato. Puede escribir un analizador para extraer el texto real del correo electrónico; podría analizar los archivos, des-base64 y fwrite() en archivos; Puedes hacer lo que quieras. Sin embargo, el alcance de su pregunta no cubre esto, y depende completamente de usted decidir cómo lo hará.

    – Kaslai

    22 de diciembre de 2011 a las 10:16

  • Lo siento, pero el mío es un proyecto “casero” que quiero ejecutar localmente y no de forma remota… así que estoy buscando algo un poco menos complicado 🙂 En el futuro implementaré funciones para que se ejecute de forma remota, pero por el momento quiero dejar que funcione localmente… 🙂 De todos modos, ¡gracias! 😀

    – usuario1111399

    22 de diciembre de 2011 a las 14:17

  • si quieres, puedes unirte a la discusión con la respuesta de dimir… 🙂 Si tienes alguna idea, ¡aquí estoy listo para leer! 🙂

    – usuario1111399

    22 de diciembre de 2011 a las 14:18

bueno, está almacenando el puntero de la estructura en el archivo, no los datos a los que apunta. Incluso si almacena la estructura que desea, es difícil obtenerla del archivo. Creo que necesitas un componente de serialización como búfer de protocolo de google. luego puede escribir un adaptador, traducir la estructura al objeto probuf, luego almacenarlo en un archivo. Cuando lo desee, retírelo. Espero que lo ayude 🙂

  • ¡Realmente aprecio tu ayuda! 😀 Pero, creo que lo resolví con la respuesta de dimir… dije “creo” porque no estoy seguro…

    – usuario1111399

    22 de diciembre de 2011 a las 13:44

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad