Vraag & Antwoord

Programmeren

[C++] Gehele Class binair wegschrijven

12 antwoorden
  • Hallo, Ik wil de inhoud van een gehele class (binairy dus) wegschrijven naar een bestand. Ben al aan de slag gegaan met fwrite/fread: [code:1:34881d67eb] FILE *file = fopen("bestand", "w"); Een_Klasse *Het_Object = new Een_Klasse(); fwrite((void*)Het_Object, sizeof(Het_Object), 1, file); fclose(file); etc. [/code:1:34881d67eb] Maar op deze manier krijg ik onomstotelijk een bestand van 4 byte... Terug lezen heb ik maar niet eens geprobeerd aangezien mijn klasse zoiezo al behoorlijk groot is. Bedankt, Barry
  • Het_Object is een pointer en de sizeof daarvan is (bijna uiteraard) 4 bytes :) Ik ken geen OO zaken, maar een [i:db6be2f427]class[/i:db6be2f427] zal niet verschillen van een [i:db6be2f427]struct[/i:db6be2f427]. Je zult er [i:db6be2f427]sizeof(Een_Klasse)[/i:db6be2f427] van moeten maken.
  • Ik heb er nu voor gekozen 1 struct met header informatie en een aantal dezelfde stucts met entry's weg te schrijven in één bestand (voolbeeld code) [code:1:b528225349] // De struct's typedef struct { QString native_string; QString target_string; bool is_fuzzy; bool is_untranslated; } dict_entry; typedef struct { QString version; QString lang_full_name; QString lang_code; } dict_header; // De schrijf code: // 'dict' is het object dat een lijst van dict_entry's bevat (entry_list) en een dict_header (header); dict->header.version = QString(VERSION); fwrite(&dict->header, sizeof(dict_header), 1, file); // Write all the entry's for(uint i =0; i < dict->entry_list->count(); i++) { fwrite(dict->entry_list->at(i), sizeof(EducatDictionary), 1, file); } // De lees code dict_header header; fread(&header, sizeof(dict_header), 1, file); // HIER segfault de code ;-) als ik bv 'cout << header.version' doe while(!feof(file)) { dict_entry entry; fread(&entry, sizeof(EducatDictionary), 1, file); dict->addEntry(entry); } fclose(file); [/code:1:b528225349] Weet iemand raad?? Dit moet toch opzich niet zo'n probleem zijn :-?
  • Voordat je gaat lezen uit de file, zul je deze eerst moeten rewinden (je filepointer staat na al je schrijfacties aan het eind van de file). Hiervoor heb je de functie [i:aa63973ff0]lseek[/i:aa63973ff0] of je kunt de file sluiten en opnieuw openen. Als je dat niet doet lees je rootzooi en een [i:aa63973ff0]printf[/i:aa63973ff0] (cout waarschijnlijk ook (man cout werkt bij mij niet)) zal dan lezen uit geheugen en printen totdat er een string terminator ('\0') wordt gevonden; grote kans dat gedurende die printf er wel ergens een geheugen locatie wordt benaderd waar je niet aan mag komen. Dit is de mogelijke oorzaak voor je segmentation fault. Indien het niet helpt, laat het even horen. Ik zal dan even een stukje voorbeeldcode schrijven (uiteraard in pure C 8) ). PS: Ik heb altijd wat problemen met pointers, zodat ik in je bestaande code zo snel niet kan zien of iets fout gaat. Ik moet het altijd even zelf schrijven. Ik heb het gevoel dat [i:aa63973ff0]dict->entry_list->at(i)[/i:aa63973ff0] geen pointer is, maar kan me vergissen.
  • Uiteraard heb ik de bestanden wel gesloten/opnieuw geopend. Dit bovenstaande is slecht een stuk code uit de lees/schrijf functie's dict->entry_list->at(i) vraagt element i op uit de linked list die ik gebruik inplaats van een array. entry_list is idd een pointer. Ik denk zelf dat het ligt aan de QString's in die struct's. QString's hebben nl. geen vaste grootte wat denk ik moeite oplevert bij het bepalen van de grootte bij het inlezen. Zal ik het eens proberen met gewone char[ ]'s met een vaste lengte?
  • Ik weet wat het probleem is, het type QString heeft geen vaste lengte dus weet ie bij het inlezen niet precies hoe veel er ingelezen moet worden. Nu heb ik de QString's in die structure vervangen voor char[ ]'s met vaste lengte, maar nu wordt mijn bestand ineens gigantisch groot... Zou het helpen als ik die char[ ] eerst steeds null-fill ??
  • Nee. Je schrijft de size van de struct weg en dat blijft hetzelfde. Als je een variabele lengte wegschrijft kun je ook nooit goed teruglezen. Je zult dan ook de lengte moeten opslaan (toevoegen aan je struct) en ieder element individueel wegschrijven. Bij het teruglezen haal je dan eerst de lengte op en dan lees je de string. Als QString iets is met variabele lengte, wat is dan sizeof(struct ...)? Ben benieuwd wat C++ daarvan maakt. Zijn er in C++ geen specifieke functies die met jouw type data overweg kunnen?
  • Nope. Ik dacht aan het volgende: Eerst gewoon met vaste lengte wegschrijven en daarna zorgen dat de \0 tekens gecomprimeerd worden. Bv: Foobar\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0 wordt Foobar\050\0 Zodat een andere functie dit weer terug kan zetten zodra een bestand ingelezen moet worden. Een hele andere manier is gewoon fprintf gebruiken....
  • Je kunt nog steeds [i:3566d739b3]fwrite[/i:3566d739b3] gebruiken. Gewoon wegschrijven met een lengte [i:3566d739b3]strlen()+1[/i:3566d739b3]. Jouw simpele compressie voorbeeld heeft een nadeel. Je moet eerst ieder karater van de string teruglezen totdat je een '\0' tegenkomt. Daarna krijg je een getal dat aangeeft hoeveel nullen er nog komen. Of je leest een bunch data in gaat die analyseren totdat je de '\0' tegenkomt. Je kunt dan net zo goed de lengte aangeven van de actuele string (fysiek voor die string). Dit werkt vele malen sneller lijkt me. Vaste lengte heeft een groot voordeel. Je kunt erg snel door een file springen doordat je exact weet waar elke struct (record) begint. Met een seek kun je bv in een keer naar het 100ste record springen. Bij variabele lengte zul je extra data (in bv een tweede file) moeten hebben die bijhoudt waar iedere struct (record) begint.
  • [quote:003a5079d6="phaas"]Hallo, Ik wil de inhoud van een gehele class (binairy dus) wegschrijven naar een bestand. Ben al aan de slag gegaan met fwrite/fread: [code:1:003a5079d6] FILE *file = fopen("bestand", "w"); Een_Klasse *Het_Object = new Een_Klasse(); fwrite((void*)Het_Object, sizeof(Het_Object), 1, file); fclose(file); etc. [/code:1:003a5079d6] Maar op deze manier krijg ik onomstotelijk een bestand van 4 byte... Terug lezen heb ik maar niet eens geprobeerd aangezien mijn klasse zoiezo al behoorlijk groot is. Bedankt, Barry[/quote:003a5079d6] FILE *file = fopen("bestand", "w"); Een_Klasse *Het_Object = new Een_Klasse(); fwrite(*(char *)Het_Object, sizeof(Het_Object), 1, file); fclose(file); try that? je schrijft nu namelijk de pointer, dus als je de inhoud van die pointer wegschrijft, hoor je logischerwijs het object te krijgen :)
  • Schrijft volgens mij nog steeds maar 4 bytes weg :( , namelijk de size van de pointer.
  • hmz... volgende keer maar eerst wakker worden... printf("%d", sizeof(Een_Klasse)); printf("%d", sizeof(*Het_Object)); FILE *file = fopen("bestand", "w"); Een_Klasse *Het_Object = new Een_Klasse(); fwrite(*(char *)Het_Object, sizeof(Een_Klasse), 1, file); fclose(file); ps: je schrijft dus een object weg, niet een klasse :)

Beantwoord deze vraag

Weet jij het antwoord op deze vraag? Registreer of meld je aan met je account

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.