Klassen in Datei speichern



  • Hey 🙂

    Wie speichert man Objekte in einer Datei um sie später wieder Lade zu können?
    Also z.b. diese Objekt:

    class _IndexTree {
    
    	public:
    		_IndexTree() {};
    	private:
    		vector<_DRBlock>	DRBlocks;	
    };
    


  • Schau mal Serialisierung im Webz.



  • Du musst einen geeigneten Ausgabeoperator definieren, der jedes Element aus dem vector ausgibt, dafür ggf. für DRBlock auch einen Operator definieren.
    Dieser Vorgang des Abspeichern nennt sich übrigens serialization.
    Wenn es ein bisschen professioneller sein soll, kannst du dir dafür auch Bibliotheken ansehen wie bspw. Boost.serialize.



  • Ok also letztendlich muss jede Klasse die ich serialisieren will, eine funktion anbieten sich selbst in serialisierter form wieder zu geben?
    also als Bytestream.

    Das geht ja eigentlich relativ fix bei einem simplen Objekt.
    Wie läuft die deserialisierung ab? hab ich dann einen konstruktor mit stream als input? oder caste ich einfach einen Pointer zu der classe von einem solchen Stream?



  • Dann hast du entsprechend einen Eingabeoperator wenn du das direkt mit den Streams machst.
    Oder du rufst die entsprechende deserialize Funktion einer Klasse auf, dazu musst du aber genau wissen, wo welche Objekte in der Datei stehen.
    Alternativ schreibst du einen Identifier in die Datei. Der wird von einer Funktion aufgerufen und je nachdem, was er ist, wird die deserialize Funktion einer bestimmten Klasse aufgerufen.



  • Das Problem kommt öfter vor: http://www.c-plusplus.net/forum/p2381207#2381207



  • ich seh schon die boost lib macht das ganz ordentlich.
    Aber wie hole ich mir Genau das was ich brauche aus der Boost lib raus?
    Ich möchte erlich gesagt nicht 100MB da mitschleifen nur weil ich die serialisierung nutzen möchte



  • folge dem Link um 13:16:05 (s.o.)



  • geht deine version auch binär?
    ich meine mein Tree wird groß genug wenn ich die werte binär speicher... da brauch ich nicht auch noch den Faktor x davor.



  • Wie sieht den _DRBlock aus? Wie viele Elemente sind es denn?

    Ja - im Prinzip auch binär. Der Königsweg wäre dann ein eigener Stream - Beispiel gibt es hier: http://www.c-plusplus.net/forum/p1935469#1935469



  • Nebenbei: Bezeichner wie _IndexTree und _DRBlock sind für die Implementation (d. h. Compiler und Standardbibliothek) reserviert. Du darfst sie nicht benutzen bzw. dich ggf. nicht über Kollisionen beschweren.

    Genaue Regeln z.B. hier: http://publib.boulder.ibm.com/infocenter/comphelp/v7v91/topic/com.ibm.vacpp7a.doc/language/ref/clrc02reserved_identifiers.htm



  • Werner_logoff schrieb:

    Wie sieht den _DRBlock aus? Wie viele Elemente sind es denn?

    Ja - im Prinzip auch binär. Der Königsweg wäre dann ein eigener Stream - Beispiel gibt es hier: http://www.c-plusplus.net/forum/p1935469#1935469

    Königsweg klingt vernünftig 😉

    Versteh ich das richtig:
    Ich brauche einen Stream, z.b. wie den den du mir zuletzt gezeigt hast. Der kann derzeit aber nur 16bit "Zahlen" speichern korrekt? dh ich muss noch die 8, 32 und 64 bit Variante ergänzen?
    Dann ist dieser Stream in der lage jede übergebene variable binär dem Stream hinzuzufügen?

    Der Konstruktor benötigt einen pointer zu einem Stream, was für einen Stream nehm ich da am besten? bzw wie sähe das erstellen des Streams aus?



  • cl90 schrieb:

    Versteh ich das richtig:
    Ich brauche einen Stream, z.b. wie den den du mir zuletzt gezeigt hast. Der kann derzeit aber nur 16bit "Zahlen" speichern korrekt? dh ich muss noch die 8, 32 und 64 bit Variante ergänzen?

    Das Erweitern auf mehrere Typen ist kein Problem. Da das immer der selbe Code ist, reicht auch ein Template. Mit C++11 sähe es dann so aus:

    class obinstream : public std::basic_ios< char >
    {
        typedef std::basic_ios< char > base_type;
    public:
        obinstream( std::streambuf* sb )
            : base_type( sb )
        {}
    
        template< typename T >
        typename std::enable_if< std::is_integral< T >::value, obinstream& >::type // erfordert #include <type_traits>
            operator<<( T x )
        {
            if( good() )
            {
                std::ios_base::iostate state = std::ios_base::goodbit;
                try
                {
                    // --   Ausgabe im little endian-format
                    for( std::size_t i = 0; i < sizeof(x); ++i, x >>= 8 )
                    {
                        if( traits_type::eq_int_type(
                            rdbuf()->sputc( static_cast< unsigned char >(x) ),
                            traits_type::eof()
                            ) )
                        {
                            state |= std::ios_base::badbit;
                            break;
                        }
                    }
                }
                catch( ... )
                {
                    state |= std::ios_base::badbit;
                    if( exceptions() & std::ios_base::badbit )
                        throw;
                }
                setstate( state );
            }
            return *this;
        }
    };
    

    damit sind schon mal alle integralen Typen möglich.

    Die Anwendung kann dann später so aussehen:

    ofstream outfile( "output.bin", std::ios_base::binary );
        obinstream out( outfile.rdbuf() );
        out << int(9) << char(9) << std::uint16_t(23) << bool(false);
    

    Zum Laden brauchst Du natürlich den passenden ibinstream .

    Gruß
    Werner



  • Ich weiss nicht ob es das schlaueste ist Serialisierung selbst zu implementieren. Also die ganzen Basis-Sachen.
    Es gibt fertige Libraries die genau dafür gemacht wurden.

    Mit denen hat man dann auch nicht auf einmal ein Problem wenn man Objekt-Graphen serialisieren (und vor allem deserialisieren) will/muss. Oder polymorphe Typen.

    EDIT: Und man ist dann auch nicht auf binäre Serialisierung beschränkt. Gerade bei der Fehlersuche kann es recht angenehm sein wenn man seine Objekte statt als BLOB mal als JSON oder XML sehen kann. /EDIT

    Ein Kandidat wäre Boost.Serialization.
    Eine 2-Sekündige Google-Orgie spuckt dann noch das als Ergebnis aus: http://uscilab.github.io/cereal/


Anmelden zum Antworten