Lesen von Binär Dateien



  • Hallo!
    Also, ich bin grad dabei ein Programm zu schreiben mit dem man Binär Dateien erstellen mit Text füllen und diese dann auch wieder lesen kann. Ein datei erstellen und was reinschreiben klappt, aber beim lesen weiß ich nicht so recht...
    Hier ist mal der Source:

    BinaryMain.cpp:

    /*
      Name: Binär Dateien Editor
      Copyright: Levin von Lenthe
      Author: Levin von Lenthe
      Date: 25.02.06 16:29
      Description: Schreiben, Lesen, Editieren... von Binär Dateien
    */
    
    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <conio.h>
    #include "console.h"
    
    using namespace std;
    
    string Name;
    int a;
    int Write();
    void Read();
    
    int main()
    {
        cls();
        cout << " ----------------------- Hauptmenue --------------------- \n\n\n\n\n";
        cout << "\n(1) Binaer Datei erstellen/schreiben\n"
             << "\n(2) Binaer Datei lesen\n"
             << "\n(3) Beenden\n";
        cout << "\nIhre Eingabe(1,2,3): ";
        cin  >> a;
    
        if (a == 1)
        {
            Write();
        }
    
        else if(a == 2)
        {
            Read();
        }
    
        else
        {
            return 0;
        }
    
        getch();
        return 0;
    }
    
    int Write()
    {
        cls();
        string name;
        string name1;
    
        cout << "Bitte geben Sie den Pfad an, wo die Datei gespeichert\nwerden soll (z.B. c:\\test.bin): ";
    
        cin >> name;
        FILE *Datei = fopen(name.c_str(), "wb");
    
        cls();
    
        cout << "Bitte geben sie nun den Text ein der der Datei hinzugefuegt\nwerden soll: ";
    
        cin >> name1;
        fwrite(&name1,sizeof(name1),1,Datei);
    
        cls();
    
        cout << "Vielen Dank!\n Die Datei ist nun unter '" << name << "' gespeichert!\n Auf Wiedersehen!";
    
        return 0;
    }
    
    void Read()
    {
         cls();
         string name;
    
         cout << "Bitte geben sie den Pfad zu der Datei an die sie lesen möchten: ";
    
         cin >> name;
         FILE *Datei = fopen(name.c_str(), "rb");
    
         getch();
    }
    

    **

    Console.cpp** // Nicht von mir geschrieben

    // -----------------------------------------------------------------------
    // Datei : Console.cpp
    // Zweck : Einige Funktionen zur Steuerung der Ausgabe im Consolen-Fenster
    // -----------------------------------------------------------------------
    
    #include "console.h" 
    
    static HANDLE hStdout; 
    static CONSOLE_SCREEN_BUFFER_INFO csbInfo; 
    
    ////////////////////////////////////////////////////////////////////////
    // Funktion setCursor() : Cursor auf die angegebene Position setzen.
    
    bool setCursor( int zeile, int spalte)
    {
        COORD dwCursorPos = {spalte, zeile};
    
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
        return SetConsoleCursorPosition(hStdout, dwCursorPos) != 0;
    }
    
    ////////////////////////////////////////////////////////////////////////
    // Funktion setColor() : Vorder- und Hintergrundfarbe setzen.
    
    bool setColor( int color)
    {
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
        return SetConsoleTextAttribute(hStdout, (WORD)color) != 0;
    }
    
    ////////////////////////////////////////////////////////////////////////
    // Funktion cls() : Consolen-Puffer mit aktuellem Attribut löschen und 
    //                  Cursor auf die Home-Position setzen.
    
    bool cls()
    {
        COORD home = { 0, 0 };          // Home-Position
        DWORD dwCellsWritten;           // Anzahl beschriebener Char-Zellen 
        DWORD dwConSize;                // Anzahl Zeichen im Puffer
    
        // Größe des Puffers und das aktuelle Attribut holen:
        hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
        GetConsoleScreenBufferInfo(hStdout, &csbInfo);
    
        dwConSize = csbInfo.dwSize.X * csbInfo.dwSize.Y;
    
        // Den Puffer mit Blanks füllen:
        if( ! FillConsoleOutputCharacter(hStdout, (TCHAR)' ', dwConSize,
                                         home, &dwCellsWritten) )
            return false;
    
        // Attribute setzen:
        if( ! FillConsoleOutputAttribute(hStdout, csbInfo.wAttributes, dwConSize,
                                         home, &dwCellsWritten) )
            return false;
    
        // Cursor auf Home-Position setzen 
    
        if( ! SetConsoleCursorPosition(hStdout, home) )
            return false;
    
        return true;
    }
    
    ////////////////////////////////////////////////////////////////////////
    // Funktion cursorOff() : Cursor unsichtbar machen.
    
    void cursorOff()
    {
        CONSOLE_CURSOR_INFO cursorInfo;   
        HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    
        GetConsoleCursorInfo( hStdout, &cursorInfo);
        cursorInfo.bVisible = FALSE;
        SetConsoleCursorInfo( hStdout, &cursorInfo);
    }
    
    ////////////////////////////////////////////////////////////////////////
    // Funktion cursorOn() : Cursor wieder sichtbar machen.
    
    void cursorOn()
    {
        CONSOLE_CURSOR_INFO cursorInfo;   
        HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    
        GetConsoleCursorInfo( hStdout, &cursorInfo);
        cursorInfo.bVisible = TRUE;
        SetConsoleCursorInfo( hStdout, &cursorInfo);
    }
    

    wär nett wenn mir einer helfen könnte thx schon mal 😉



  • Howdy!
    Nundenn, du verwendest fuer deine ganzen Datei-Operationen C-Funktionen. Was ziemlich uncool ist, du willst ja C++ schreiben 😉
    Aber die gute Nachricht ist: in C++ sind Datei-Operationen wesentlich einfacher als mit C: weil das ganze fast genauso funktioniert wie cin/cout, und das kennst du ja schon 🙂

    Also vergiss einfach fopen(), fwrite, fread() & co. In C++ macht man das ganze ueber "fstreams". Dazu gibts einen netten Eintrag in der FAQ des Forums: http://www.c-plusplus.net/forum/viewtopic-var-t-is-39469.html

    Vielleicht werden deine Fragen ja da schon beantwortet, wenn nein: frag nach dem lesen einfach nochmal hier 🙂



  • ahh danke werds mir gleich mal durchlesen 🙂



  • soo...
    Hab jetzt alles hoffentlich auf aktuellen C++ Stand gebracht ^^
    aber ich hab immer noch ein problem und zwar mit dem lesen der Binär Datei.
    Hier nochmal der Source(in neuer Fassung):

    /*
      Name: Binär Dateien Editor
      Copyright: Levin von Lenthe
      Author: Levin von Lenthe
      Date: 25.02.06 16:29
      Description: Schreiben, Lesen, Editieren... von Binär Dateien
    */
    
    #include <iostream>
    #include <string>
    #include <fstream>
    #include <conio.h>
    #include "console.h"
    
    using namespace std;
    
    string Name;
    int a;
    int Write();
    void Read();
    
    int main()
    {
        cls();
        cout << " ----------------------- Hauptmenue --------------------- \n\n\n\n\n";
        cout << "\n(1) Binaer Datei erstellen/schreiben\n"
             << "\n(2) Binaer Datei lesen\n"
             << "\n(3) Beenden\n";
        cout << "\nIhre Eingabe(1,2,3): ";
        cin  >> a;
    
        if (a == 1)
        {
            Write();
        }
    
        else if(a == 2)
        {
            Read();
        }
    
        else
        {
            return 0;
        }
    
        getch();
        return 0;
    }
    
    int Write()
    {
        cls();
        string name;
        string name1;
    
        cout << "Bitte geben Sie den Pfad an, wo die Datei gespeichert\nwerden soll (z.B. c:\\test.bin): ";
    
        cin >> name;
        ofstream getAdress(name.c_str(),ios::out|ios::binary);
    
        cls();
    
        cout << "Bitte geben sie nun den Text ein der der Datei hinzugefuegt\nwerden soll: ";
    
        cin >> name1;
        ofstream write(name1.c_str());
    
        cls();
    
        cout << "Vielen Dank!\n Die Datei ist nun unter '" << name << "' gespeichert!\n Auf Wiedersehen!";
    
        return 0;
    }
    
    void Read()
    {
         cls();
         string name;
         char buf[255];
    
         cout << "Bitte geben sie den Pfad zu der Datei an die sie lesen möchten: ";
    
         cin >> name;
         ifstream getAdress(name.c_str(),ios::in|ios::binary);
    
         while(getAdress.good())
         {
                                getAdress.read(buf,255);
                                cout << buf;
         }
    
    }
    

    Ich kann den Speicherort wo die Datei ist auch eingeben aber wenn es dann ans ausgeben geht, wirds komisch... Eine kurze Anzahl von komischen Zeichen erscheint auf dem Bildschirm ... ??? Hä.. Help Please :p



  • Du legst zwar eine Datei unter dem Namen an, den der Benutzer dir gibt - aber du schreibst nichts da rein (also hast du letztendlich eine 0 Byte Datei).
    Und beim Lesen solltest du überprüfen, wieviele Daten du überhaupt bekommen hast (getAdress.gcount()) - aktuell liest du gar nichts ein (die Datei war leer, siehe oben) und gibtst anschließend den Inhalt deines Puffers aus, der mit willkürlichen Werten initialisiert wurde.



  • Wieso?? Ich frag doch ab was in die Datei geschrieben werden sol..?



  • Ja, Du fragst ab was in die Datei geschrieben werden soll.
    Nein, Du schreibst es nicht in den Stream "getAddress".



  • oha... stimmt... ich trottel ^^
    und was mach ich falsch beim lesen??? 😮

    void Read()
    {
         cls();
         string name;
         char buf[255];
    
         cout << "Bitte geben sie den Pfad zu der Datei an die sie lesen möchten: ";
    
         cin >> name;
         cls();
         setColor(3);
         ifstream fileOut(name.c_str(),ios::in|ios::binary);
         if( !fileOut)
         {
             openError();
         }
    
         else
         {
         while(!fileOut.eof())
         {
                                fileOut.read(buf,255);
                                cout << buf;
         }
         }
         fileOut.close();                       
    }
    

    Jetzt hab ich auch noch ein Problem Beim schreiben... Ich krieg eine Fehlermledung nachdem ich den Text der in die Datei geschrieben werden soll eigegeben habe die meistens immer ungefähr so lautet:

    Die Anweisung in "0x77c17000 verweist auf Speicher in "0x003d4000". Der Vorgan "read" konnte nicht auf dem Speicher durchgeführt werden.

    Klicken Sie auf "OK", um das Programm zu beenden.
    Klicken Sie auf "Abbrechen", um das Programm zu debuggen.

    😮
    hää???



  • @p3ac3:
    Ändere

    fileOut.read(buf,255);
    cout << buf;
    

    nach

    fileOut.read(buf, 254);
    buf[fileOut.gcount()] = '\0';
    cout << buf;
    ...
    

    Merke: operator<<(ostream& os, char*) ließt aus char bis zum Auftreten des '\0'-Zeichens. Wenn du dieses nicht selbst setzt, wird von &buf[0] aus solange aus dem Speicher gelesen, bis entweder das Nullterminierungszeichen gefunden wird, oder aber, weil dir der Speicher aus dem du ließt nicht gehört, es crasht. => Undefiniertes Verhalten = (manchmal geht alles Gut und manchmal - meistens dann, wenn man es am wenigsten gebrauchen kann, chrasht es).

    Gruß Caipi



  • danke 🙂
    jetzt bleibt nur noch das problem beim schreiben. Hab den code nochmal bearbeitet:

    void Write()
    {
        cls();
        string name;
        string name1;
    
        setCursor(10,1);
        cout << "Bitte geben Sie den Pfad an, wo die Datei gespeichert\nwerden soll (z.B. c:\\Hallo.bin): ";
    
        cin >> name;
        ofstream FileIn(name.c_str(),ios::out|ios::binary);
        if( !FileIn)
         {
             openError();
         }
    
        cls();
    
        cout << "Bitte geben sie nun den Text ein der der Datei hinzugefuegt\nwerden soll: ";
    
        cin >> name1;
        if( !FileIn.write( (char*)name1.c_str(), sizeof(name1)) )
        {
            writeError();
        }
    
        cls();
        FileIn.close();
    
        cout << "Vielen Dank!\n Die Datei ist nun unter '" << name << "' gespeichert!\n Auf Wiedersehen!";
    }
    

    was mach ich nur falsch... 😮

    EDIT: Ein teil des Problems hat sich gelöst. Ich hatte einen schreibfehler. Aber das problem ist das er beim schreiben in die Datei nur bis zur ersten leerstelle schreibt... und dann aufhört. Wie krieg ich das weg 😕



  • p3ac3 schrieb:

    if( !FileIn.write( (char*)name1.c_str(), sizeof(name1)) )
    

    Hier ist das Problem: sizeof(name1) gibt nicht die Länge des Strings zurück, sondern die Größe der Datenstruktur die diesen String speichert. Wenn sich das zufällig mit dem ersten Leerzeichen in deinem Text überschneidet ➡ Zufall.

    Die Länge des enthaltenen Strings liefert Dir name1.length()



  • if( !FileIn.write( (char*)name1.c_str(), name1.length()))
    

    habs jetzt so ist aber immer noch das gleiche prob... 😞



  • p3ac3 schrieb:

    Aber das problem ist das er beim schreiben in die Datei nur bis zur ersten leerstelle schreibt... und dann aufhört. Wie krieg ich das weg 😕

    Der istream& operator>>(istream&, string&) ließt nur bis zum nächsten Blank, also (Leerzeichen, Tabstop, New-line, ...). => Verwende die Funktion getline().

    edit: Was mir jetzt erst auffällt:

    if( !FileIn.write( (char*)name1.c_str(), name1.length()))
    

    ist sehr unsauber. (Merke: std::string::c_str() gibt einen const char* zurück. Wenn du diesen in char* castest und dann auf diesen Speicherbereich etwas schreibst erzeugst du undefiniertes Verhalten!).

    Gruß Caipi



  • Er schreibt ja hier auch nichts rein. Den Cast kann man sich hier übrigens sparen.



  • Braunstein schrieb:

    Er schreibt ja hier auch nichts rein. Den Cast kann man sich hier übrigens sparen.

    Jup. Meine Aussage gilt natürlich nur für fstream::read(). (Weiß wirklich nicht, wie es mir gelingt, immer wieder solche "Schussel"-Fehler in die Posts einzubauen 🙄).

    Gruß Caipi



  • Caipi schrieb:

    Braunstein schrieb:

    Er schreibt ja hier auch nichts rein. Den Cast kann man sich hier übrigens sparen.

    Jup. Meine Aussage gilt natürlich nur für fstream::read(). (Weiß wirklich nicht, wie es mir gelingt, immer wieder solche "Schussel"-Fehler in die Posts einzubauen 🙄).

    Gruß Caipi

    ja,... aber das problem is ja auch beim schreiben. Wenn ich mir diedatei dann anschaue nachdem ich was reingeschrieben habe ohne dieses Programm steht auch nur immer das erste word... (Komisch überhaupt das ich die datei lesen kann, wo sie doch eigentlich binär sein sollte...)
    😮



  • 1. Wie genau liest du die Datei ein und zeigst sie an? Womöglich ist dort ein NULL-Byte dazwischen, das die Kontollausgabe beendet.

    2. Klar kannst du auch die binären Daten lesen, wenn du Text dort reingeschrieben hast. In einer Binärdatei stehen genauso char's wie in einer Textdatei.

    (der einzige Unterschied zwischen den Dateimodi ist die Art, wie Newlines behandelt werden - Binärdateien überlesen sie ohne Sonderbehandlung, Textdateien passen sie ans Betriebssystem an (Windows verwendet \r\n, C++ übersetzt das in ein einfaches \n)).

    PS@Mods: Warum steht das eigentlich noch nicht in den FAQs? So oft wie diese Frage in letzter Zeit kam.



  • Hallo,

    Hinweis für Strings:
    Wenn man Strings binär rausschreibt sollte man vorher dort die Länge mit ablegen, sonst weiß man beim späteren Einlesen dann nicht wieviele Bytes gelesen werden sollen.
    etwa so

    // rausschreiben
    int size = name1.length();
    FileIn.write( (char*)size, sizeof(size));
    FileIn.write( (char*)name1.c_str(), name1.length()));
    
    //einlesen
    int size;
    FileIn.read( (char*)size, sizeof(size));
    char* buffer = new char[size+1];
    FileIn.read( buffer, size);
    buffer[size] = '\0';
    name1 = buffer;
    delete[] buffer;
    


  • hallo,
    meine Funktionen read() und write() sehen jetzt so aus:

    void Write()
    {
        cls();
        string name;
        string name1;
    
        setCursor(10,1);
        cout << "Bitte geben Sie den Pfad an, wo die Datei gespeichert\nwerden soll (z.B. c:\\Hallo.bin): ";
    
        cin >> name;
        ofstream FileIn(name.c_str(),ios::out|ios::binary);
        if( !FileIn)
         {
             openError();
         }
    
        cls();
    
        cout << "Bitte geben sie nun den Text ein der der Datei hinzugefuegt\nwerden soll: ";
    
        cin >> name1;
        int size = name1.length();
    
        FileIn.write( (char*)size, sizeof(size));
        if( !FileIn.write( name1.c_str(), name1.length()))
        {
            writeError();
        }
    
        cls();
        FileIn.close();
    
        cout << "Vielen Dank!\n Die Datei ist nun unter '" << name << "' gespeichert!\n Auf Wiedersehen!";
    }
    
    void Read()
    {
         cls();
         string name;
    
         setCursor(10,1);
         cout << "Bitte geben sie den Pfad zu der Datei an die sie lesen moechten: ";
    
         cin >> name;
         cls();
         ifstream FileOut(name.c_str(),ios::in|ios::binary);
         if( !FileOut)
         {
             openError();
         }
    
         else
         {
            int size; 
    
            FileOut.read( (char*)size, sizeof(size)); 
            char* buffer = new char[size+1]; 
            FileOut.read( buffer, size); 
            buffer[size] = '\0'; 
            name = buffer; 
            delete[] buffer;
         }
    

    Aber beim schreiben wird das Programm einfach nachdem ich angegeben habe was in die Datei geschrieben werden soll angegeben habe beendet, wieder mit dieser "Fehler in Der Anwendung" fehlermeldung -> Die Anweisung "0x00435dd9" ... blabla.
    ??



  • Geh doch mal mit dem Debugger durch und schau wo abgebrochen wird. Desweiteren wirst du beim einlesen mit cin Schwierigkeiten bei Trennzeichen (Leerzeichen oder so) bekommen, da dann hier abgebrochen wird. Nimm lieber getline.


Anmelden zum Antworten