Написание и чтение (fwrite - fread) структур с указателями - PullRequest
2 голосов
/ 22 декабря 2011

Я работаю над проектом почтового ящика, и у меня есть эти две структуры:

struct mmbox_mail

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

и

mail_t

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

Я не могу изменить поля структур, потому что мне нужны переменные данные (для этой цели я использовал char * вместо char []).

Каждая структура mail_t является почтой. Мне нужно сохранять каждую почту пользователя в файл, который может быть двоичным или текстовым файлом (но я думаю, что лучше с двоичным файлом, потому что у меня есть тело void*, которое трудно сохранить в простом тексте.

Я пытался сделать это, но похоже, что это не работает:

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 */

Не могли бы вы мне помочь? Я пытался искать везде, но так и не нашел человека, который попросил бы сохранить две структуры, одна внутри другой.

Ответы [ 3 ]

3 голосов
/ 22 декабря 2011

Конечно, это не будет работать, так как для строк он будет копировать размер указателя (обычно 4 байта).Я вижу здесь 3 варианта:

  1. Сериализация данных, двоичный файл (http://en.wikipedia.org/wiki/Serialization).
  2. Создание формата для хранения данных в текстовом файле.
  3. Использование языка разметки, например XML /JSON и т. Д.

В любом случае вам нужно будет пройти через каждое поле структуры, чтобы записать его в файл данных. Что касается чтения, то в первых двух случаях вам придется выполнять чтение точнов том порядке, в котором вы записали данные, в третьем случае вы сможете читать поля независимо в любом порядке.

Если вы выберете первый метод, для каждого поля строки (char *) запишите также нулевой байт завершениячтобы вы всегда знали, где он заканчивается, когда читаете его обратно.

0 голосов
/ 22 декабря 2011

хорошо, вы сохраняете указатель структуры в файл. Не те данные, на которые он указывает. Даже когда вы сохраняете нужную структуру. Трудно получить ее из файла.я думаю, что вам нужен компонент сериализации, как Google Procal буфер .затем вы можете написать адаптер, перевести структуру в объект probuf, а затем сохранить его в файл. Если хотите, повторите его. В этом вам поможет:)

0 голосов
/ 22 декабря 2011

Что вы делаете, это сохраняете буквальное двоичное представление mail_t в текстовый файл, который является просто набором указателей.То, что вы хотите сделать, это что-то с эффектом:

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

, который отобразит значения, указанные в виде строки, и сохранит их в файле.Указатель на место в памяти, которое хранится в вашем приложении, для большинства людей становится немного бесполезным после закрытия указанного приложения;)

РЕДАКТИРОВАТЬ: «Не могли бы вы помочь мне?чтобы сохранить две структуры, одна внутри другой. "

Если бы у вас просто были первоклассные типы данных, такие как int или float и т. д., ваш метод работал бы отлично.Однако, поскольку вы используете типы второго класса, а именно массивы char и void, вам необходимо указать способ сохранения указанных данных.

...