Problem mit Database, in der '\0' vorkommt



  • Hallo, ich habe folgendes Problem:

    ich habe eine Database.txt (ca. 5MB), in der Allerhand Sonderzeichen vorkommen. Diese Sonderzeichen werden nur benutzt, um die Daten in der Datei zu trennen. Leider ist eines der Sonderzeichen '\0' (also das Nullterminierende Zeichen). Wenn ich jetzt die Datei per ifstream einlesen will, bricht das Einlesen natürlich immer bei den NULL Zeichen ab. Ich habe schon versucht, das ganze über .clear() oder .get() und isprintable() abzufangen, allerdings ohne Erfolg.

    Hat jemand eine Ahnung, wie ich so eine Datei handeln kann? Und wie sieht dann die "Abbruchbedingung" für das Einlesen aus? while(!is.eof()) geht ja dann nicht mehr...

    Vielen Dank für alle Ideen!


  • Administrator

    1. Verwende std::ios::binary :
    http://www.cplusplus.com/reference/iostream/ios_base/openmode/
    2. while(!is.eof()) ist sowieso meistens eine schlechte Idee. Das eofbit Flag wird erst gesetzt, nachdem man über das Ende hinausgelesen hat. Man sollte die Gültigkeit des Streams immer nach einer Leseoperation prüfen, davor bringt eigentlich nicht viel.

    Grüssli



  • Schonmal Danke für den Tipp!

    Ich habe jetzt im binary Modus eingelesen, und tatsächlich wird nicht beim ersten Nullzeichen abgebrochen. Allerdings scheint isprint() nicht im binary modus zu funktionieren.

    Mein Asatz ist Folgender: Der Sinn ist, alle Sonderzeichen zu entfernen und mit Zeilenumbrüchen zu ersetzen

    vector<unsigned char>vec; //Vektor zum Zwischenspeichern anlegen
    
    ifstream lesen ("Master.mwBase", ios::in | ios::binary); //öffnen im binary modus
    
    unsigned char c;
    while(!lesen.eof()) //ganze Datei lesen
    {
        c = lesen.get(); //Buchstabenweise lesen
    
        if(!isprint(c)) //Sonderzeichen ersetzen. Scheint im binarymodus
           c='\n';      //nicht zu funktionieren
        vec.push_back(c);
    }
    lesen.close();
    
    ofstream out;
    out.open("output.txt", ios::out | ios::binary);
    
    for(unsigned int t(0);t!=vec.size();++t)
        out<<vec[t]; //Database ohne sonderzeichen in Outputdatei scheiben
    out.close();
    

    Denn die Output Datei ist jetzt eine 1:1 Kopie der Originaldatei (mit Sonderzeichen).
    Was mache ich falsch?



  • StreamProblem schrieb:

    Was mache ich falsch?

    Naja, du prüfst ja noch nicht mal irgendwo nach Sonderzeichen.

    Übrigens kann man Dateien auch in einem Rutsch einlesen:

    ifstream file( "...", ios::binary );     // Datei öffnen
    file.seekg( 0, ios::end );               // Dateizeiger an's Ende setzen
    size_t file_size = file.tellg();         // Dateigröße ermitteln
    file.seekg( 0, ios::beg );               // Dateizeiger wieder an den Anfang
    
    std::vector<char> content( file_size );  // vector erstellen mit genug Elementen
    file.read( &content[0], file_size );     // Alles einlesen
    

    Was bezeichnest du eigentlich als "Sonderzeichen", also wie grenzt du sie ein?

    Und: Bei ifstream brauchst du das Flag ios::in nicht übergeben, ist implizit.

    edit: Und geschlossen werden die Dateien automatisch mit dem Destruktor, das brauchst du nicht manuell zu machen 🙂



  • Und: Bei ifstream brauchst du das Flag ios::in nicht übergeben, ist implizit.
    edit: Und geschlossen werden die Dateien automatisch mit dem Destruktor, das brauchst du nicht manuell zu machen

    Das wusste ich noch garnicht. Wieder was gelernt 😃

    Naja, du prüfst ja noch nicht mal irgendwo nach Sonderzeichen.

    Das Prüfen der Sondereichen wollte ich über isprint(c) realisieren

    Was bezeichnest du eigentlich als "Sonderzeichen", also wie grenzt du sie ein?
    

    In dem Textdokument selber sehe ich die Sonderzeichen nur als "Kästchen". Wenn ich die Datei einlese, werden mit diese Zeichen als Smileys, Herzen, "ý" oder ähnlichem angezeigt. Und natürlich das null Zeichen. Diese habe ich versucht über isprint(c) herauszufiltern.

    Den Tipp mit der ganzen Datei einlesen werde ich gleich mal ausprobieren 😃



  • StreamProblem schrieb:

    Naja, du prüfst ja noch nicht mal irgendwo nach Sonderzeichen.

    Das Prüfen der Sondereichen wollte ich über isprint(c) realisieren

    Ohje, sorry, hab ich total übersehen 😕

    Der Fehler in deinem Code war ein fehlendes "else" nach Zeile 11 🙂

    Wenn du die Datei in einem Rutsch liest und schreibst ( outfile.write(&content[0],content.size()) ), kannst du zum Ersetzen (nach Lesen, vor Schreiben) einen Algorithmus aus der STL verwenden: std::replace_if.



  • Ok, der Ansatz von Badestrand funktioniert einwandfrei.

    Vielen Dank! 🙂



  • Badestrand schrieb:

    StreamProblem schrieb:

    Naja, du prüfst ja noch nicht mal irgendwo nach Sonderzeichen.

    Das Prüfen der Sondereichen wollte ich über isprint(c) realisieren

    Ohje, sorry, hab ich total übersehen 😕

    Der Fehler in deinem Code war ein fehlendes "else" nach Zeile 11 🙂

    Das leuchtet mir nicht ein 😕



  • Belli schrieb:

    Das leuchtet mir nicht ein 😕

    Mir auch nicht mehr, war wohl zu spät.


Anmelden zum Antworten