C ++ Двійкові файли Зберегти динамічну структуру в бінарний файл
Увага!
Можна використовувати подвійний прохід по файлу. Першим порахувати кількість структур, виділити необхідну кількість пам'яті і другим прочитати все структури з файлу. Такий спосіб краще. Мій приклад менш безпечний і швидше несе тільки теоретичну користь, а не практичну
Питання як зберегти динамічну структуру в бінарний файл мене зацікавив сильно і відразу після мого першого досвіду успішної роботи з двійковими файлами. Для тих хто тільки що почав все вивчення з ++, сам сенс використання динамічних структур, об'єктів, класів поки не так очевидний.
Я перерив пошук вздовж і поперек, але не знайшов нічого путнього з цього приводу. В основному було наведено приклад, в якому використовується статична змінна.
Можна використовувати різні способи. Перші мої думки були порахувати число об'єктів і записати його в початок файлу, вважати його звідти як лічильник і потім виконати цикл по цьому лічильнику. Так, такий варіант цілком нормальний, але мені хотілося інакше, щоб в бінарний файл не записувалося нічого зайвого. У підсумку я знайшов один із способів вирішення. Далеко не найкращий спосіб, але я знаю, що багато людей навіть так придумати не в змозі.
Код C ++ Зберегти / Прочитати динамічну структуру в бінарний файл
Іншими словами. Записати динамічну структуру в файл можна точно також як записати звичайну змінну.
Із записом в бінарний файл розібралися. Виявляється це не так складно, але виникає питання по прочитанню. Як прочитати з бінарного файлу кілька структур.
Тепер, після того як ми вважали все в одну купу, всю цю купу даних за вказівником TempY можна вивести на екран, використовуючи лічильник count та цикл for. Хтось може заспокоїтися і вирішити, що це все, що більше нічого не потрібно. Але хто так подумає, той зробить глобальну помилку. Якщо ви згадаєте, то побачите, що під TempY спочатку не виділялося пам'яті, а значить будь-які отримані дані можуть бути вигнані зі своїх осередків як нелегальні поселенці. Таке виселення даних з комірок може привести до непередбачуваних наслідків і поетом всіх треба переселити туди, звідки їх ніщо не вижене. Для цього і використаний третій покажчик. Число структур відомо і пораховано, значить виділяємо під третій покажчик стільки пам'яті, скільки потрібно і за допомогою циклу переселяємо дані динамічних структур з небезпечною осередки в безпечну
Мою ідею легко довести до розуму якщо вміти використовувати динамічні списки і в такому випадку отримаєте безпечне читання структур з файлу за один раз.
1. tempY був ініціалізованим першим нулем, а потім в нього почалося циклічне зчитування файлу, причому на кожній ітерації в один і той же ділянку пам'яті (невідомо в який). Це загрожує тим, що tempY може вказувати, наприклад, на ділянку пам'яті, зайнятий іншої змінної. Програма перезапише цю змінну і все - трійка, сімка, туз - програмі привіт (це в кращому випадку). Щоб щось записати в tempY під неї потрібно спочатку виділити пам'ять.
2. Так як x і y - указаелі, то операції sizeof X і sizeof Y дадуть розміри покажчиків, а не масивів цілком.
Я думаю, що читання і запис правильніше було б переписати так:
1. Запис у файл:
out.write ((char *) X, sizeof (MyStruct) * 5); // так як X - покажчик, то оператор '' тут не потрібен
2. Читання з файлу (якщо невідомо кількість записаних в файл структур (але, імхо, якщо вже записувати в файл масив структур, то в першому рядку простіше вказати розмір масиву)):
struct MyStruct * tempY = new struct MyStruct;
struct MyStruct * temp = 0;
struct MyStruct * y = 0;
int count = 0;
std :: ifstream in;
in.open ( «123.txt», std :: ios :: binary | std :: ios :: in);
while (in.read ((char *) tempY, sizeof (struct MyStruct))) *Пока не достигнут конец файла*/
count ++;
PS: Для виділення пам'яті в даному випадку простіше використовувати malloc / realloc, скоротитися код.
Чи не шедевр, звичайно, але мені здається, що так буде більш коректно.