Как записать структуру в бинарный файл?
есть двусвязный список, с помощью него считывается/записывается информация в бинарный файл
typedef struct data{
char name[16];
char sex[16];
char sport[16];
int birthday;
int growth;
}dataT;
typedef struct node{
dataT* data;
struct node* next, *prev;
}node;
typedef struct hwnd{
size_t size;
node* head, *tail;
}hwnd;
int main(int agrc, char** argv)
{
char s[16], c; int x;
hwnd* hwnd = createHwnd();
FILE* file = fopen("vector", "rb+");
unloadData_FromFile(file, hwnd);
//список обновляется, перезаписываем файл
file = fopen("vector", "wb+");
uploadData_ToFIle(file, hwnd->head);
return 0;
}
функции считывания записи
void unloadData_FromFile(FILE* file, hwnd* hwnd)
{
dataT* pData = (dataT*)malloc(sizeof(dataT)); //память под данные узла
while(fread(pData, sizeof(dataT), 1, file))
{
node* temp = (node*)malloc(sizeof(node)); //память под узел
temp->data = pData;
uploadList(temp, hwnd);//добавляем узел в список
}
fclose(file);
return;
}
void uploadData_ToFIle(FILE* file, node* head)
{
while(head){
fwrite(head->data, sizeof(dataT), 1, file);
head = head->next;
}
fclose(file);
}
Считывание из файла в структуру работает, запись из структуры в файл работает не корректно (н-р, было 9 записей в структуре, в файл 9 раз запишется последний элемент) Почему так происходит?
void uploadList(node* temp, hwnd* hwnd){
temp->prev = hwnd->tail;
temp->next = NULL;
if (hwnd->tail)
hwnd->tail->next = temp;
else
hwnd->head = temp;
hwnd->tail = temp;
}
Ответы (2 шт):
У вас создается указатель в памяти, куда вы пишете считываемые из файла данные.
dataT* pData = (dataT*)malloc(sizeof(dataT)); //память под данные узла
При этом в новый узел, вставляемый в список, вы данные не копируете, а просто указываете на них:
temp->data = pData;
Результат - вы получаете 9 узлов, указатель на данные которых указывает на одно и то же место в памяти. Понятно, что при каждом чтении из файла данные перезаписываются, вот вы и получаете 9 последних записей.
Попробуйте копировать данные:
node* temp = (node*)malloc(sizeof(node)); //память под узел
temp->data = (dataT*)malloc(sizeof(dataT));
memcpy(temp->data,pData,sizeof(dataT));
uploadList(temp, hwnd);//добавляем узел в список
Пара замечаний:
- в случае ошибки при чтении в функции
unloadData_FromFile()у вас происходит утечка памяти, т.к.pDataне удаляется - неправильно обрабатывается возврат функции
fread(). Правильно проверять что считалось нужное количество байт, а всё остальное - ошибка. В случае ошибки чтения не обязательно вернется0fread().
И кстати, возврат функции fwrite() тоже нужно проверять, но там ошибки реже бывают.
Да и выделение памяти желательно проверить.
Ещё как вариант - вы можете в struct node держать не указатель на объект struct data, а сам объект. Тогда у вас повысится быстродействие - вместо 2 операций new (а они дорогие!) останется только одна. И чтение данных будет выглядеть также, как и запись:
typedef struct node
{
dataT data; // объект, а не указатель
struct node *next, *prev;
} node;
void unloadData_FromFile(FILE* file, hwnd* hwnd)
{
while(true)
{
node* temp = (node*)malloc(sizeof(node)); //память и под узел и под данные
// выделение памяти тоже желательно проверить вот здесь!
if( fread( &(temp->data), sizeof(dataT), 1, file) == sizeof(dataT) )
uploadList(temp, hwnd);//добавляем узел в список
else
{
delete temp;
return;
}
}
}
void uploadData_ToFIle(FILE* file, node* head)
{
while(head){
fwrite( &(head->data), sizeof(dataT), 1, file);
head = head->next;
}
}