Objekt binär schreiben und lesen



  • Hallo zusammen,
    ich bin ziemlich neu in c++ und versuche gerade eine Datei binär zu schreiben und zu lesen.

    Das schreiben habe ich hinbekommen, zumindest glaube ich das, weil da irgendwelche komischen Zeichen in der Text-Datei sind, obwohl ich mir eher dachte, dass da nur 0 und 1 stehen würden.

    Nun versuche ich das auszulesen, was ich eben geschrieben habe und das klappt nicht.
    Zuerst, wie ich schreibe:

    ofstream outFile(dateiname.c_str(), ios::out | ios::binary);
        if (outFile.good()) {
    
            outFile.write((char*) &*(this), sizeof (this));
    
        }
        outFile.close();
    

    Ist das so korrekt? Ich möchte einfach, dass "this"-Objekt binär abzuspeichern.

    Wie ich versuche zu lesen:

    string text("");
        Matrix mTmp;
        ifstream inFile(dateiname.c_str(), ios::in | ios::binary);
    
        inFile.seekg(0, ios::end); //Zeiger auf den ersten Block der Datei palzieren
        //mit tellg sagen, ab wo er lesen soll:
        unsigned long fileSize = std::streamoff(inFile.tellg()); //mit 
        inFile.seekg(0, ios::beg); //Das hab ich ausprobiert und er zeigt mir ein  
                                  //komisches Zeichen an, sonst zeigt er gar nix an
                                  //Viele Fragezeichen im Kopf^^
    
        char* pBuffer = new char[fileSize];
        inFile.read(pBuffer,1);
        //Auf der Konsole zeigt er mir ein Pfeil nach oben, womit ich nix anfangen  
        //kann. Ich weiss nicht genau, wie man das interpritieren soll, was man 
        //ausließt
        cout << "Erstes zeichen: " << *pBuffer << "\n";
    

    Ich hoffe, mir kann jemand erklären, wie man binäre Dateien ausließt und sie interpritiert.
    Danke für jeden Tipp.



  • Öhh, du und viele andere Anfänger haben da immer so ein doofes Verständnisproblem was Zahlenbasen angeht. Alles im PC ist binär. Wenn da 5 steht, dann ist das bloß anders dargestellt, im Hintergrund ist aber dennoch 00000101 gespeichert. Wenn du dann char s hast in pBuffer (wieso dieses p? Wir sind hier nicht in C), dann ist die Information wie immer binär gespeichert. Wenn du nun aber auf der Konsole Nullen und Einsen ausgeben möchtest, dann musst du noch eine Funktion schreiben, die die Bits ausliest und ausgibt.

    Zur Erklärung was ios::binary macht ( ios::in und ios::out sind übrigens sinnlos, du machst schon std::ifstream und std::ofstream , das impliziert das Flag, egal ob du es tatsächlich schreibst):
    Auf verschiedenen PCs werden die Zeilenumbrüche unterschiedlich dargestellt. Wir können C++ einfach nur '\n' sagen, und es wählt das korrekte Zeichen für die Plattform aus (ebenso beim Lesen). Beim binären Modus geht man davon aus, dass da Daten (kein Text und daher keine Zeilenumbrüche) drin sind, von denen ein Byte nun einmal denselben Wert haben kann wie '\n' . Daher wird das im Binärmodus nicht mehr umgewandelt.



  • Du kannst nicht mal so eben ohne Weiteres Objekte deiner eigenen Klasse binär abspeichern.

    Nehmen wir mal an, du willst einen int binär speichern. Dann stehen in der Datei sagen wir mal 4 Byte (auf einem x86 System), liest du diese 4 Byte und interpretierst sie als int kriegst du deinen Startwert wieder raus.
    Schreibst du 4 ints und liest auch wieder 4 ints, kriegst du deine Startwerte.

    Schreisbt du jedoch eine Liste von ints (ohne die Länge anzugeben), woher weist du dann wie viele ints du geschrieben hast?
    Da musst du dir ein Format überlegen. z.B: du schreisbt erst ein int was die Länge angibt und danach die x-vielen ints. Und so kannst du das auch wieder einlesen.

    Hast du jetzt aber ein Objekt eienr Klasse, musst du dieser Klasse auch beibringen wie sie sich selbst binär ein- und ausgibt. Und wenn Zeiger da drin sind, wird das nochmal komplizierter.

    Serialisierung ist kein einfaches Thema, aber umgekehrt auch kein ungelöstet Problem.

    In deinem Code gibt es zudem ein Problem bei der Ausgabe:

    outFile.write((char*) &*(this), sizeof (this));
    

    Du wandelst dein Objekt in eine CharSequenz um, aber sagst, dass nur die ersten 4 (oder 😎 Bytes/chars geschrieben werden sollen. Müsste *sizeof(this) heissen.



  • std troll schrieb:

    Öhh, du und viele andere Anfänger haben da immer so ein doofes Verständnisproblem was Zahlenbasen angeht. Alles im PC ist binär. Wenn da 5 steht, dann ist das bloß anders dargestellt, im Hintergrund ist aber dennoch 00000101 gespeichert.

    Es ist aber in C++ wie in x86 irrelevant, dass die Hardware binär rechnet. Davon bekommt man gar nichts mit. Die kleinste adressierbare und manipulierbare Einheit ist typischerweise so groß wie char und hat 256 verschiedene Zustände. Alles im PC ist also 256-är.



  • vielen Dank für die Antworten.
    Die Lösung war tatsächlich (*this).
    Ich habe versehntlich die gespeicherte Adresse serialisiert und nicht den Inhalt selbst...

    Also er funktioniert super, daher kann ich nicht ganz nachvollziehen, warum ich nicht einfach ohne weiteres serialisieren kann....
    Ich musste noch nicht mal die Membervariablen beim Auslesen interpritieren.
    Danke



  • Das musst du dann nicht, wenn es die Basisdatentypen(int, char, long, double etc.) sind.

    Aber pack mal einen std::string in deine Klasse und mach dein Programm mal zwischendurch aus. Also starte es neu.



  • ahso, also wenn ich einen enum, oder eine Unterklasse, oder gar nen String habe, hätte das dann komplizierterweise interpritieren müssen?

    noch eine kleine Frage, und zwar warum sagt mir die Netbeans IDE, dass folgendes Zuweisung:

    char* wert = "Hallo";
    depricated ist? (also verwaltet). Er zeigt ja dennoch auf "H" am Anfang.
    Und wie mache ich das "modern" ?
    Danke



  • Wenn dann müsste es const char * wert = "..."; heißen, denn auf einen char* kannst du auch schreibend zugreifen, was dann knallen würde.

    Und in modernem C++ wäre das std::string wert = "Hallo";

    @Nachtrag: Deprecated ist veraltet und nicht verwaltet.



  • Skym0sh0 schrieb:

    Deprecated ist veraltet und nicht verwaltet.

    Weder - noch.



  • Aber sinngemäß meistens schon. Laut Leo wäre die korrekte Übersetzung "überholt".

    Also veraltet trifft es weit besser verwaltet...



  • Ich empfinde den Schritt von ablehnen/mißbilligen zu für veraltet erklären halt als recht groß.
    Naja...


  • Mod

    @deprecated: Auch neue Sachen können deprecated werden, wenn sich heraus stellt, dass sie Mist waren.



  • TyRoXx schrieb:

    std troll schrieb:

    Öhh, du und viele andere Anfänger haben da immer so ein doofes Verständnisproblem was Zahlenbasen angeht. Alles im PC ist binär. Wenn da 5 steht, dann ist das bloß anders dargestellt, im Hintergrund ist aber dennoch 00000101 gespeichert.

    Es ist aber in C++ wie in x86 irrelevant, dass die Hardware binär rechnet. Davon bekommt man gar nichts mit. Die kleinste adressierbare und manipulierbare Einheit ist typischerweise so groß wie char und hat 256 verschiedene Zustände. Alles im PC ist also 256-är.

    Ja, das waren noch Zeiten als ich zwischen AL und AH Daten hin- und hergeschoben, XORed usw. hab. Lange her.



  • SeppJ schrieb:

    @deprecated: Auch neue Sachen können deprecated werden, wenn sich heraus stellt, dass sie Mist waren.

    Okay, ja das triffts was besser, was ihr beiden sagt.

    Können wir uns drauf einigen, dass man Deprecated Dinge einfach nach Möglichkeit nicht mehr nutzen soll?


Anmelden zum Antworten