[c++] Binair file lezen/schrijven

Pagina: 1
Acties:
  • 116 views sinds 30-01-2008
  • Reageer

  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
Ik heb een functie die mijn object (van de klasse CPreferences) binair wegschrijft naar een bestand.

C++:
1
2
3
4
5
void WritePreferences( CPreferences prefs, char *pref_filename )
{
    ofstream outfile( filename, ios::binary );
    outfile.write( (char *)&prefs, sizeof( CPreferences ) );
}


Als ik deze functie aanroep, als mijn applicatie afsluit, wordt het bestand netjes geschreven.

Nu wil ik dus dat het bestand weer wordt ingelezen als de applicatie start. Met de volgende aanroep:

C++:
1
ReadPreferences( *Preferences, "preferences\\mri_prefs.dat" );


met de bijbehorende functie:

C++:
1
2
3
4
5
void ReadPreferences( CPreferences &prefs, char *filename )
{
    ifstream infile( filename, ios::binary );
    infile.read( (char *)&prefs, sizeof( CPreferences ) );
}


Preferences is vantevoren al gedeclareerd en geinitialiseerd middels zijn constructor (de gebruiker krijgt de default waarden als de file niet gelezen kan worden). Ik krijg dus bij het inlezen van het binaire bestand een "access violation error".

Iemand die misschien wat het probleem kan zijn.

  • curry684
  • Registratie: Juni 2000
  • Laatst online: 13-08 16:46

curry684

left part of the evil twins

Waarom doe je zo wazig dereferencen om een pointer by-reference door te kunnen geven? :?

Ennuh is die Preferences variabele wel zeker weten geinitialiseerd?

Professionele website nodig?


  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Ik weet niet wat er precies in je CPreferences class staat maar als je daar virtual methods in gebruikt wordt ook de vftable pointer (pointer naar een array van virtual function pointers) weggeschreven naar je bestand. Die pointer is dan niet meer geldig als je het later weer gaat inlezen (waarschijnlijk de access violation).
Je kunt beter je class member voor member wegschrijven en inlezen, dan weet je zeker dat alleen de dingen weggeschreven worden die je er ook echt in wil.

www.madwizard.org


  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
ik heb in de ReadPreferences functie de & weggehaald bij de parameters, heb dit ooit zo eens bedacht :? lijkt me ook kloppen nu.

ik krijg nu inderdaad geen access violation, maar CPreferences lijkt zich niks aan te trekken van de instellingen in de file. hij pakt gewoon de waarden die ie meekrijgt uit z'n constructor en dus niet de waarden die daarna pas uit de file zouden moeten worden gelezen.

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Da Snake schreef op 08 november 2002 @ 11:35:
ik heb in de ReadPreferences functie de & weggehaald bij de parameters, heb dit ooit zo eens bedacht :? lijkt me ook kloppen nu.

ik krijg nu inderdaad geen access violation, maar CPreferences lijkt zich niks aan te trekken van de instellingen in de file. hij pakt gewoon de waarden die ie meekrijgt uit z'n constructor en dus niet de waarden die daarna pas uit de file zouden moeten worden gelezen.
Als je de & weghaalt wordt de class by value meegegeven (oftwel een kopie net als dat bij een primitive zoals een int gebeurt), wat je dan wijzigt is de parameter zelf en niet de class die je bedoelt zodat ie inderdaad ongewijzigd blijft. Die & klopt wel, het probleem staat in m'n vorige post.

www.madwizard.org


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Da Snake schreef op 08 november 2002 @ 11:35:
ik heb in de ReadPreferences functie de & weggehaald bij de parameters, heb dit ooit zo eens bedacht :? lijkt me ook kloppen nu.

ik krijg nu inderdaad geen access violation, maar CPreferences lijkt zich niks aan te trekken van de instellingen in de file. hij pakt gewoon de waarden die ie meekrijgt uit z'n constructor en dus niet de waarden die daarna pas uit de file zouden moeten worden gelezen.
Ja, duh. Zonder de & heb je pass-by-value, dan kopieer je de CPreferences en overschrijf je de kopie.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 21-08 17:14
Je kunt overigens alleen PODs binair inlezen (POD = Plain Old Data, object dat je in C ook had kunnen declareren)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
madwizard schreef op 08 november 2002 @ 11:42:
[...]


Als je de & weghaalt wordt de class by value meegegeven (oftwel een kopie net als dat bij een primitive zoals een int gebeurt), wat je dan wijzigt is de parameter zelf en niet de class die je bedoelt zodat ie inderdaad ongewijzigd blijft. Die & klopt wel, het probleem staat in m'n vorige post.
inderdaad ja, klopte ook...
heb inderdaad arrays binnen die klasse gedefinieerd, dus dat is waarschijnlijk het probleem, maar om het member voor member te doen is geen werk en ook niet echt netjes, aangezien ik toch echt alles weg wil schrijven, geen andere opties om iets binair weg te schrijven...

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Da Snake schreef op 08 November 2002 @ 11:55:
heb inderdaad arrays binnen die klasse gedefinieerd, dus dat is waarschijnlijk het probleem, maar om het member voor member te doen is geen werk en ook niet echt netjes, aangezien ik toch echt alles weg wil schrijven, geen andere opties om iets binair weg te schrijven...
Zolang je geen pointers of andere members met data die alleen runtime zinnig is (dus ook geen geneste classes) kun je het wel direct wegschrijven. Je moet er alleen rekening mee houden dat je compiler ook extra informatie aan de class toevoegt die je niet mag wegschrijven.
Je kan het data gedeelte wel bij elkaar houden in je class:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
class Blah
{
public:
    Blah ();
    virtual ~Blah();
    struct _data
    {
        int     test;
        int     test2;
        double  nogiets;
    } data;
};

De struct in je class kan je veilig lezen & schrijven.
C++:
1
2
char *pData = reinterpret_cast<char*>(&blah.data);
int iDataSize = sizeof(blah.data);

Op deze manier moet je alleen wel je code omschrijven omdat de variabelen nu niet class.x heten maar class.data.x. Je kunt ook een naamloze struct gebruiken:
C++:
1
2
3
4
5
6
7
8
9
10
11
12
class Blah1
{
public:
    Blah1 ();
    virtual ~Blah1();
    struct
    {
        int     test;
        int     test2;
        double  nogiets;
    };
};

Het adres en de grootte van de struct krijgen is nu wel lastiger, het adres is gelijk aan het adres van het eerste element, de grootte kan op deze manier:
C++:
1
2
3
4
5
char *pData = reinterpret_cast<char*>(&blah.test);
// size = adres laatste element - adres eerste element + grootte laatste element
int size = (reinterpret_cast<char*>(&b1.nogiets) +
            sizeof(b1.nogiets) - 
            reinterpret_cast<char*>(&b1.test));

Dit is wel erg goor, ik weet niet of er een betere methode is om de grootte te achterhalen, wie het weet mag het zeggen :).

www.madwizard.org


  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
ok ik werk niet met structs binnen deze classes
wel met arrays, bv float *bgcolor = { r, g, b };
dit zou dus gewoon moeten werken?

  • madwizard
  • Registratie: Juli 2002
  • Laatst online: 26-10-2024

madwizard

Missionary to the word of ska

Da Snake schreef op 08 november 2002 @ 13:25:
ok ik werk niet met structs binnen deze classes
wel met arrays, bv float *bgcolor = { r, g, b };
dit zou dus gewoon moeten werken?
Een array binnen de class (class A { int arr[100]; } ) gaat wel goed, een pointer niet...

www.madwizard.org


  • Krooswijk.com
  • Registratie: Mei 2000
  • Laatst online: 17-08-2024
dat was het ja:

float *bgcolor = { r, g, b };

moet zijn:

float bgcolor[3];

  • unclero
  • Registratie: Juni 2001
  • Laatst online: 08:20

unclero

MB EQA ftw \o/

Wat dacht je van:

Lezen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char *buffer;
long f_size;
ifstream bestand;

bestand.open("bla.bin",ios::in | ios::binary | ios::nocreate);
if(!bestand.is_open()) { cout << "Gatsie... niet open\n"; }
f_size = bestand.tellg();
buffer = new char [f_size];
bestand.seekg(0,ios::beg);
bestand.read(buffer);
bestand.close;
/* bestand in een buffer.. */
/* doe wat je ermee wilt.. */

delete [] buffer; /* Gooi de buffer weg.. */


Schrijven:

C++:
1
2
3
4
ofstream bestand;
bestand.open("bla.bin",ios::out | ios::binary | ios::trunc);
bestand.puts("\x01");  /* IIRC */
bestand.close();

Quelle chimère est-ce donc que l'homme? Quelle nouveauté, quel monstre, quel chaos, quel sujet de contradiction, quel prodige!


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

unclero schreef op 08 november 2002 @ 14:22:
Wat dacht je van:

Lezen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char *buffer;
long f_size;
ifstream bestand;

bestand.open("bla.bin",ios::in | ios::binary | ios::nocreate);
if(!bestand.is_open()) { cout << "Gatsie... niet open\n"; }
f_size = bestand.tellg();
buffer = new char [f_size];
bestand.seekg(0,ios::beg);
bestand.read(buffer);
bestand.close;
/* bestand in een buffer.. */
/* doe wat je ermee wilt.. */

delete [] buffer; /* Gooi de buffer weg.. */


Schrijven:

C++:
1
2
3
4
ofstream bestand;
bestand.open("bla.bin",ios::out | ios::binary | ios::trunc);
bestand.puts("\x01");  /* IIRC */
bestand.close();


waarom zou je het bestand in een buffer gooien? Maak dan gewoon een memberfunctie (of losse friend functie) dat een instantie van CPreferences kan laden en schrijven dmv streams

bijvoorbeeld:
C++:
1
2
3
4
5
6
7
class CPreferences
{
public:
    CPreferences (istream &);
    ...
    void write (ostream &);
};

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • abeker
  • Registratie: Mei 2002
  • Laatst online: 28-08 15:41

abeker

...

unclero schreef op 08 november 2002 @ 14:22:
Wat dacht je van:

Lezen:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
char *buffer;
long f_size;
ifstream bestand;

bestand.open("bla.bin",ios::in | ios::binary | ios::nocreate);
if(!bestand.is_open()) { cout << "Gatsie... niet open\n"; }
f_size = bestand.tellg();
buffer = new char [f_size];
bestand.seekg(0,ios::beg);
bestand.read(buffer);
bestand.close;
/* bestand in een buffer.. */
/* doe wat je ermee wilt.. */

delete [] buffer; /* Gooi de buffer weg.. */
[miereneuk-mode]
Bij het openen van een bestand, staat de get-pointer op 0 dus dit voorbeeldje gaat niet werken. Na het openen van het bestand dit toevoegen.
C++:
1
bestand.seekg(0,ios::end);
[/miereneuk-mode]

En ik zou een member functie gebruiken of operator<< overloaden om de gegevens mee weg te schrijven. (hmm .oisyn is me voor...)

the less one forgets, the less one remembers


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 29-08 03:21

.oisyn

Moderator Devschuur®

Demotivational Speaker

De << en >> operatoren zijn bedoeld voor een text-representatie, en die overloaden lijken me dus niet geschikt (zorgt voor verwarring)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • abeker
  • Registratie: Mei 2002
  • Laatst online: 28-08 15:41

abeker

...

ah ja ik zie het nu ook in de MSDN staan, weer wat geleerd :)

the less one forgets, the less one remembers

Pagina: 1