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!
-
1. Verwende
std::ios::binary:
http://www.cplusplus.com/reference/iostream/ios_base/openmode/
2.while(!is.eof())ist sowieso meistens eine schlechte Idee. DaseofbitFlag 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 einlesenWas 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 machenDas 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.