Daten abspeichern
-
Hi Leute,
habe als absoluter Anfänger mit eurer Hilfe bzw. der Hilfe der Forenbeiträge geschafft einen
Code zu schreiben mit dem man Datensätze zeilenweise einlesen kann.
Lediglich mit Ausgabe in eine von mir gewählte Datei habe ich meine Probleme. Zwar erstellt
er mir die Datei, schreibt aber nix rein.
Wieso?
Danke für eure Hilfe!Hier der Code:
#include <iostream> #include <fstream> #include <string> using namespace std; int main(void) { //char hilf; char *daten; char buffer[1024]; //zeilenweise int dateigroesse,i=0; //Einagbebereich ifstream datein; string datei; string Puffer; cout <<"Bitte Pfad eingeben!"<< endl; cout <<"Kompletter Quellpfad: "; cin >> datei; datein.open(datei.c_str(), ios_base::in); ofstream dataus; cout <<"Bitte Pfad eingeben!"<<endl; cout <<"Kompletter Zielpfad: "; cin >> datei; //dataus.open(datei.c_str(), ios_base::out); if (datein.good) { i=0; datein.seekg(0L,ios::end); //ios::end, Dateizeiger vom Ende der Datei aus bewegen. dateigroesse = datein.tellg(); datein.seekg(0L,ios::beg); //ios::beg, Dateizeiger vom Anfang der Datei aus bewegen. daten = new char[dateigroesse+1]; while(datein.good()) { //zeilenweise einlesen datein.getline(buffer,1024); cout << buffer << "\n"; //zeilenweise // Ausgabe; bzw Bearbeitung dataus.open(datei.c_str(), ios_base::app); i++; } datein.close(); dataus.close(); } else { cout << "FEHLER keine Datei gefunden!" <<endl; } delete[] daten; return 0; }
-
Du liest zwar aus der Datei offenbar ein aber ein paar Dinge sind total unlogisch.
Dort wo die Datei eigentlich geöffnet werden soll hast du dies auskommentiert, stattdessen öffnest du sie bei jedem Durchgang deiner while-Schleife (statt etwas hinauszuschreiben, da muss ein Aufruf von write() hin, oder Vergleichbares).
Desweiteren legst du einen riesengroßen Puffer für die gesamte Datei aus der du einliest an. Dieser wird aber nie benützt
MfG SideWinder
-
Hi,
irgendwie muss icih doch lediglich den buffer ansprechen!
ofstream dataus; //???? ifstream dataus; cout <<"Bitte Pfad eingeben!"<<endl; cout <<"Kompletter Zielpfad: "; cin >> datei; dataus.put(datei.c_str(), ios_base::app); if (datein.good) { i=0; datein.seekg(0L,ios::end); //ios::end, Dateizeiger vom Ende der Datei aus bewegen. dateigroesse = datein.tellg(); datein.seekg(0L,ios::beg); //ios::beg, Dateizeiger vom Anfang der Datei aus bewegen. daten = new char[dateigroesse+1]; while(datein.good()) { //zeilenweise einlesen datein.getline(buffer,1024); cout << buffer << "\n"; //zeilenweise // Ausgabe; bzw Bearbeitung dataus.put(buffer); i++; } datein.close(); dataus.close(); } else { cout << "FEHLER keine Datei gefunden!" <<endl; } delete[] daten; return 0; }
Ich ahbe jetzt das Öffnen der neuen Datei nach oben verschoben. Ich denke, dass die Lösung nahe ist. Kann mir keiner helfen?
Gruß
-
hier mal ein Vorschlag von mir und diesmal habe ich versucht so wenig vom Code zu ändern wie geht:
also:
ich würde vorschlagen die Namen der Ein- und Ausgabedatei als c-Array abzulegen, dann kannst du nämlich das Deklarieren, Definieren und Öffnen der Dateien einfacher gestaltenint main() { const int MAX_LEN=80; char datei[MAX_LEN]; char * daten; char buffer[1024]; int dateigroesse, i=0; string Puffer; //wozu dient Puffer????? cout <<"Bitte Pfad eingeben!"<< endl; cout <<"Kompletter Quellpfad: "; cin >> datei; ifstream datein(datei); //Eingabestrom cout <<"Bitte Pfad eingeben!"<<endl; cout <<"Kompletter Zielpfad: "; cin >> datei; ofstream dataus(datei); //Ausgabestrom if( datein && dataus ) //Ein- und Ausgabedatei konnte geöffnet werden { datein.seekg(0L,ios::end); dateigroesse = datein.tellg(); datein.seekg(0L,ios::beg); daten = new char[dateigroesse+1]; while(datein.good()) { datein.getline(buffer,1024); cout << buffer << "\n"; dataus << buffer <<endl; //schreiben in Ausgabedatei i++; //wozu dient i????? } delete[] daten; //Freigabe des dyn allok Speichers nur, wenn er auch angelegt datein.close(); //eigentlich nicht notwendig; geschieht von selber bei Verlassen des Progs dataus.close(); } else { cerr << "FEHLER keine Datei gefunden!" <<endl; } return 0; }
-
post scriptum:
wenn Du jedoch lediglich den Inhalt der Eingabedatei in die Ausgabedatei kopieren möchtest geht auch wunderbar:dataus<<datein.rdbuf(); //Inhalt der Eingabedatei in die Ausgabedatei kopieren
und falls du danach wieder von Anfang der Eingabedatei lesen willst:
datein.seekg(0,ios::beg);//Lesezeiger auf Anfang der Eingabedatei zurücksetzen
Außerdem würde ich beim Benutzen von getline der Fkt auch mitgeben bis zu welchem delimiter eine Zeile eingelesen werden soll, zB bis ein Zeilenumbruch \n o.ä
bezogen auf dein Bsp:datein.getline(buffer, 1024, '\n');
-
Wow! Danke!
Das war ja fast ein Onlinekurs von dir! Ich werde deine Beiträge sofort ausprobieren!
Mittlerweile habe ich auch selbst eine funktionierende Variante erschaffen:
//Code liest zeilenweise ein und gibt in eine zu bestimmende Datei aus! #include <iostream> #include <fstream> #include <string> using namespace std; int main(void) { //char hilf; char *daten; char buffer[1024]; //zeilenweise, buffer lässt Zeilenlänge bis 1024 zu int dateigroesse,i=0; //Eingabebereich ifstream datein; string datei; string Puffer; cout <<"Bitte Pfad eingeben!"<< endl; cout <<"Kompletter Quellpfad: "; cin >> datei; datein.open(datei.c_str(), ios_base::in); //Ausgabebereich ofstream dataus; string datraus; //ifstream dataus; cout <<"Bitte Pfad eingeben!"<<endl; cout <<"Kompletter Zielpfad: "; cin >> datraus; //dataus.open("d:\\test2.txt"); dataus.open(datraus.c_str(), ios_base::out); if (datein.good) { i=0; datein.seekg(0L,ios::end); //ios::end, Dateizeiger vom Ende der Datei aus bewegen. dateigroesse = datein.tellg(); datein.seekg(0L,ios::beg); //ios::beg, Dateizeiger vom Anfang der Datei aus bewegen. daten = new char[dateigroesse+1]; while(datein.good()) //Vorgang wiederholen, solange Daten in Zeile vorhanden { //zeilenweise einlesen datein.getline(buffer,1024); cout << buffer << "\n"; //zeilenweise // Ausgabe; bzw Bearbeitung dataus << buffer<<"\n"; //Zugriff auf die gerade geöffnete Zeile i++; } datein.close(); dataus.close(); } else { cout << "FEHLER keine Datei gefunden!" <<endl; } delete[] daten; return 0; }
Danke für deine Hilfe!
Ich finde es super wie einem hier im Forum geholfen wird!Gruß
-
Hallo,
eure Versionen schreiben eine Zeile zuviel.while(datein.good()) //Vorgang wiederholen, solange Daten in Zeile vorhanden
{
//zeilenweise einlesen
datein.getline(buffer,1024);Das ist käse, da das eof-Bit erst gesetzt wird, *nachdem* eof gelesen wurde. Das heißt deine Bedigung dateien.good() liefert erst false *nachdem* dateien.getline scheiterte. Dummerweise schreibst du in diesem Fall aber trotzdem den Inhalt von buffer.
Lösung:
while (datein.getline(buffer,1024)) { ... }
Merksatz: Tests wie stream.good() oder !stream.eof() sind in der Regel *keine* guten Schleifenbedingungen. Vielmehr sollte in einer Schleifenbedingung immer das Ergebnis einer Lese- oder Schreibaktion getestet werden.
-
@HumeSikkins: thanx' hast ja recht und es sieht auch viel eleganter aus; ist wohl noch viel von den 'ninety percent' in unserem Code
aber warum ist das denn schlimm, da bei dem letzten getline doch nur die Endekennung der Datei in den c-string gelesen wird, der Rest dessen damit auch initialisiert wird, und dieser delimiter am Ende doch von getline wieder aus dem c-string gelöscht wird.ich hoffe, daß ich mich verständigen konnte
-
Danke HumeSikkins,
habe deine Ergänzung/Verbesserung übernommen! Funktioniert natürlich!
Gruß
-
freshman schrieb:
aber warum ist das denn schlimm, da bei dem letzten getline doch nur die Endekennung der Datei in den c-string gelesen wird, der Rest dessen damit auch initialisiert wird, und dieser delimiter am Ende doch von getline wieder aus dem c-string gelöscht wird.
Das Ergebnis ist in *diesem* konkreten Fall unproblematisch, da lediglich ein '\n' mehr geschrieben wird (buffer enthält im letzten durchlauf nur einen Leerstring - dataus << buffer ist damit eine Noop und es wird nur das abschließende "\n" geschrieben).
Die Logik des Programm ist aber dennoch kaputt. Abstrakt kannst du dir das ja so vorstellen:
while(eingabe.good()) { readFromEingabe(); processRead(); writeRead(); }
Im letzten Durchlauf wird processRead und writeRead() aufgerufen, obwohl gar nichts gelesen wurde. Es wird also auf Daten gearbeitet die in der Eingabedatei gar nicht existieren.
Die Logik (und besonders der Kommentar an der while-Schleife) suggeriert aber, dass in der Schleife immer nur gültige Eingabe-Daten verarbeitet werden.Abhängig von der konkreten Implementation von readFromEingabe, processRead und writeRead können hier unterschiedliche Probleme auftreten.
In diesem konkreten Fall hast du aber wie gesagt nur das Problem, dass Ein- und Ausgabedatei nicht gleich sind, da die Ausgabedatei ein '\n' mehr enthält - für ein Kopierprogramm nicht gerade gewünschtes Verhalten
-
da soll mal einer drauf kommen. thanx'
aber heißt das denn dann, daß dataus<<buffer; auf jeden Fall eine Leerzeile in die Ausgabe schreibt, auch wenn buffer komplett leer ist??
@HumeSikkins: sorry, wegen der Nerv-mail
-
freshman schrieb:
aber heißt das denn dann, daß dataus<<buffer; auf jeden Fall eine Leerzeile in die Ausgabe schreibt, auch wenn buffer komplett leer ist??
Ne. Dafür sorgt das << "\n" nach dem dataus << buffer