PDA

View Full Version : [C++] Creare un file contenete l'istanza di una classe..


Emalele1688
16-03-2010, 22:16
Salve a tutti!!

E' da un pò che mi chiedo diverse domande per quanto riguarda l'argomento File in c++.
Fino ad oggi ho sempre usato fread ed fopen per leggere e scrivere file, ma se volessi fare di più, come creare un File contenente l'istanza di una classe come faccio??

Esempio:

NomeClasse* obj = new NomeClasse();

Voglio salvare l'oggetto puntato da obj su un file (anche un file binario), come faccio??

Si può magari anche definire un nuovo formato di file?? Come??

fero86
17-03-2010, 00:55
premessa: in C++ non si usano fopen e fread, quelle fanno parte della libreria di I/O del C. in C++ si usa fstream. to': http://www.cplusplus.com/reference/iostream/fstream/



Si può magari anche definire un nuovo formato di file?? Come?? come ti pare: hai carta bianca, il significato di ogni singolo byte lo decidi tu.

Emalele1688
17-03-2010, 19:03
Si quello l'ho capito, ma come salvo sul disco il singolo byte?? Che API uso per interfacciarmi con la memoria di massa??

sadino90
17-03-2010, 19:42
Se non ho capito male basta che copi il contenuto degli attributi della classe nel file... ovviamente non a casaccio ma dandogli un minimo di struttura (se è solo una classe ti basta mettere un attributo per riga, per dire)

tomminno
17-03-2010, 19:48
Si quello l'ho capito, ma come salvo sul disco il singolo byte?? Che API uso per interfacciarmi con la memoria di massa??

Quello che stai cercando di fare te si chiama serializzazione. In C++ non è una operazione banale. La serializzazione binaria è poi dipendente dal compilatore.

Una versione minimale e funzionante solo nei casi estremamente semplici è:

NomeClasse nc;

ofstream ofs("NomeClasse.bin", ios::binary);
ofs.write((char *)&nc, sizeof(nc));


Ci sono varie librerie per la serializzazione che gestiscono anche i casi più complessi come s11n.net e boost.

fero86
18-03-2010, 00:06
Si quello l'ho capito, ma come salvo sul disco il singolo byte?? metodo write di ostream, ereditata da fstream.



Che API uso per interfacciarmi con la memoria di massa?? non si usano API per accedere alla memoria principale, il linguaggio permette di accedervi direttamente... :stordita:
il metodo write di cui sopra prende tra i parametri un puntatore ai dati (situati in memoria principale) che vuoi scrivere sullo stream :stordita:



Se non ho capito male basta che copi il contenuto degli attributi della classe nel file... "basta"? ma perché, il problema qual era? salvare lo stato di un oggetto su un file mi pare che voglia dire salvare lo stato dei singoli campi, o no? :mbe:

se l'oggetto contiene due campi interi e un booleano tu salvi sul file due interi e un booleano; se contiene un double e una struttura o classe contenente a sua volta tre interi tu salvi il double e poi i tre interi. poi quando rileggi il file sei in grado di costruire un oggetto che ha lo stesso identico stato, o no?

la situazione si complica quando un oggetto contiene dei puntatori a qualcos'altro, ma li devi vedertela tu a seconda di cosa significano e come vuoi gestire quei puntatori.



ovviamente non a casaccio ma dandogli un minimo di struttura (se è solo una classe ti basta mettere un attributo per riga, per dire) be', io finora ho ipotizzato che tu salvassi in formato binario (infatti ti dicevo di usare ostream::write) ma naturalmente puoi anche inventare un formato testuale; anzi, il formato testuale é d'obbligo se devi evitare problemi di endianness.



Quello che stai cercando di fare te si chiama serializzazione. In C++ non è una operazione banale. non é un'operazione banale se vuoi realizzare un'infrastruttura generica che possa funzionare con qualunque oggetto, ma se gli oggetti sono tuoi e sai come sono fatti a me pare una stronzata, poi magari mi sfugge qualcosa.

sadino90
18-03-2010, 09:08
"basta"? ma perché, il problema qual era? salvare lo stato di un oggetto su un file mi pare che voglia dire salvare lo stato dei singoli campi, o no? :mbe:

se l'oggetto contiene due campi interi e un booleano tu salvi sul file due interi e un booleano; se contiene un double e una struttura o classe contenente a sua volta tre interi tu salvi il double e poi i tre interi. poi quando rileggi il file sei in grado di costruire un oggetto che ha lo stesso identico stato, o no?


Provo ad azzardare una cosa, che non ho mai fatto, spero di non dire una cavolata :D
I puntatori ovviamente ti possono puntare ad un altro oggetto anch'esso abbastanza complesso con strutture al suo interno e magari altri puntatori. Di certo non ti puoi salvare il valore del puntatore perchè sarebbe la locazione di una cella di memoria e quindi poi non riusciresti più a risalire al tuo oggetto. In questo caso puoi fare una creazione di file in cascata, ogni qual volta trovi un puntatore ad un oggetto crei un nuovo file contenente tale oggetto e nel file dove dovresti metterci il puntatore a questo oggetto metti il nome del file dove esso viene salvato. Troppo macchinosa come cosa?
Ovviamente se vuoi evitare la creazione di un sacco di file puoi fare tutto all'interno dello stesso file però io personalmente non mi avventurerei in una cosa del genere :D

fero86
18-03-2010, 13:10
Provo ad azzardare una cosa, che non ho mai fatto, spero di non dire una cavolata :D
I puntatori ovviamente ti possono puntare ad un altro oggetto anch'esso abbastanza complesso con strutture al suo interno e magari altri puntatori. Di certo non ti puoi salvare il valore del puntatore perchè sarebbe la locazione di una cella di memoria e quindi poi non riusciresti più a risalire al tuo oggetto. In questo caso puoi fare una creazione di file in cascata, ogni qual volta trovi un puntatore ad un oggetto crei un nuovo file contenente tale oggetto e nel file dove dovresti metterci il puntatore a questo oggetto metti il nome del file dove esso viene salvato. se vuoi... ripeto, hai carta bianca, fai un po' come ti pare; se ti conviene fare cosi fai cosi.



Ovviamente se vuoi evitare la creazione di un sacco di file puoi fare tutto all'interno dello stesso file però io personalmente non mi avventurerei in una cosa del genere :D perché? anzi, ti risparmi la creazione di un altro file e la relativa gestione degli errori.

Emalele1688
18-03-2010, 21:56
Scusate la domanda banale, ma per quanto riguarda Linux so bene che non ci sono problemi con l'estensione del file da creare (correggetemi se sbaglio), ma in Windows devo usare per forza il .bin o me lo posso inventare io???

A me interessa farlo tanto in Windows come in Linux...

tomminno
18-03-2010, 22:05
Scusate la domanda banale, ma per quanto riguarda Linux so bene che non ci sono problemi con l'estensione del file da creare (correggetemi se sbaglio), ma in Windows devo usare per forza il .bin o me lo posso inventare io???

A me interessa farlo tanto in Windows come in Linux...

E' solo un esempio, l'estensione non ha alcun significato specifico, potresti usare txt o pdf o docx o non usarla affatto.
Solo che facendo doppio click il programma di default associato a quella estensione ti avviserà che il file è corrotto (eccetto il txt) e questo comportamento lo otterrai sia su Linux che su Windows.

Emalele1688
23-03-2010, 20:51
Già immaginavo... Dunque anche in questo caso si ricorre agli stream del c++ ...

tomminno
23-03-2010, 22:27
Già immaginavo... Dunque anche in questo caso si ricorre agli stream del c++ ...

Devi considerare che quello funziona in casi banali di classi contenitore.
Se la tua classe contiene un puntatore o peggio ancora un riferimento quello che ottieni rileggendo il file è qualcosa di inutilizzabile.
Infine per gli stream, essendo il linguaggio C++, è il modo più naturale per scrivere su un file, niente vieterebbe di usare le funzioni C per l'accesso ai file.

Emalele1688
24-03-2010, 20:09
E se io volessi creare un file, che contiene classi ed altri file, per esempio file di testo o addirittura immagini...
Praticamente sto facendo un piccolo gioco (molto cretino a scopo didattico) e voglio salvare lo stato del giocatore... Le informazioni necessarie sono contenute in una classe, e se volessi inserire nel file un'immagine??