Как сохранить динамическую структуру в файл - PullRequest
2 голосов
/ 17 августа 2011

У меня есть что-то вроде этого, на самом деле более сложная структура, чем эта:

typedef struct _sample {
    unsigned char type;
    char *name;
    test *first;
} sample;
typedef struct _test {
    test *prev;
    test *next;
    char *name;
    int total;
    test_2 **list;
} test;
typedef struct _test_2 {
    char *name;
    unsigned int blabla;
} test_2;
sample *sample_var;

Я хочу сделать резервную копию этой структуры в файл и после его восстановления.

Я также пытаюсь использовать fwrite(sample_var, sizeof(sample), 1, file_handle);, но настоящая проблема в sizeof(sample), которая возвращает неправильный размер, а не реальный размер переменной.

Есть способ сохранить его в файл и восстановить, не зная размера?

Ответы [ 4 ]

4 голосов
/ 17 августа 2011

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

Вам придется определить свою собственную сериализацию /функции десериализации.Вы можете использовать свой собственный простой формат или использовать JSON , XML , XDR или что-то в этом роде.

Лично я бы пошел с JSONтак как в наши дни это все в моде в любом случае.

Кроме того, вот C FAQ , смутно связанный с вашим собственным вопросом (хотя в нем обсуждаются вопросы взаимодействия).

1 голос
/ 17 августа 2011

Нет простого способа сохранить такую ​​структуру в файл. Например, даже поле sample.name имеет размер 4 (в зависимости от архитектуры), а то, что вы, вероятно, хотите сохранить, - это содержимое памяти, на которое указывает sample.name.

Вот пример кода, который сделает такую ​​вещь. Вам придется продублировать процесс, чтобы сохранить всю структуру.

void saveToFile(FILE *fh, sample s)
{
  fwrite(s.type, sizeof(char), fh);
  int nameSize = strlen(s.name); // get the length of the name field
  fwrite(nameSize, sizeof(size_t), fh); // write the length of the name field
  frwite(s.name, nameSize * sizeof(char), fh); // write the content of the name field
  // continue with other fields
}

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

0 голосов
/ 17 августа 2011

Похоже, что вы действительно хотите сохранить структуру и то, на что ссылаются ее указатели, а не сами указатели.

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

0 голосов
/ 17 августа 2011

sizeof (sample) не является неправильным: он возвращает размер символа, за которым следуют два указателя. Если вам нужно сохранить такой рекурсивный тип данных, вы должны вручную разыменовать указатели.

...