Anzahl der Zeichen in einer Textdatei auslesen?



  • Hallo liebes Forum,

    ich lese eine Textdatei mit:

    ifstream file( example.txt );
    

    ein.

    Wie kann ich nun herausfinden, wieviele Zeichen sich in dieser Datei befinden?

    Google half mir leider garnicht.

    Vielen Dank schonmal.


  • Mod

    Wenn du sie tatsächlich einliest: Mitzählen?

    Falls du es schon vor dem Einlesen wissen möchtest:
    Etwas frickelig, aber portabel: Ans Ende springen (seekg), dann Position mit tellg bestimmen.
    Direkt, aber streng genommen nicht portabel (gibt es aber auf allen gängigen Betriebssystemen): stat-Funktion des Betriebssystems benutzen. In Boost Filesystem gibt es auch eine entsprechende Funktion, wenn dir Boost lieber ist.

    In beiden Fällen erhält man jedoch die Größe der Datei, was nicht unbedingt mit der Anzahl der Zeichen identisch ist, die man daraus lesen kann (außer im binary-Modus).


  • Mod

    Googlen will gelernt sein.
    Vierter Link bei Google: c++ size of a file:
    http://stackoverflow.com/questions/5840148/how-can-i-get-a-files-size-in-c

    Etwas frickelig

    Pardon?


  • Mod

    Arcoth schrieb:

    Etwas frickelig

    Pardon?

    Also schön finde ich die Methode nicht.



  • Arcoth schrieb:

    Googlen will gelernt sein.

    [...]

    Pardon?

    www.google.de/search?q=frickelig


  • Mod

    Belli schrieb:

    ...

    Es ging nicht darum, das mir das Wort fremd war. Und das erste Ergebnis auf Google definiert es mit "widerspenstig". Diese Methode ist nicht widerspenstig, und genau deswegen habe ich ja widersprochen.

    Also schön finde ich die Methode nicht.

    Ich auch nicht, aber deswegen ist sie nicht frickelig. Sie ist nur leider nicht so direkt.
    Was spricht überhaupt gegen einen size() -Member von filebuf?



  • Bei Unicode hilft dann doch aber nur Zeichen zählen, oder?



  • Arcoth schrieb:

    Belli schrieb:

    ...

    Es ging nicht darum, das mir das Wort fremd war. Und das erste Ergebnis auf Google definiert es mit "widerspenstig".

    Dann würd es ja so ein bisschen auf Dich passen ...
    Aber so wie ich Dich mittlerweile einschätze, und das ist durchaus positiv gemeint, würdest Du Dich doch nicht mit dem ersten Link zufrieden geben und noch ein paar weitere aufrufen, um Dir ein Gesamtbild zu machen ...
    Dass es Dir da gar nicht drum ging, hab ich mir zwar gedacht, aber ich wollte nichts in Dein Posting hineininterpretieren und hab es deshalb so genommen, wie es dort stand - so gut ich konnte, jedenfalls.



  • CppNeuland schrieb:

    Bei Unicode hilft dann doch aber nur Zeichen zählen, oder?

    Bei UTF-8 und UTF-16, ja.


  • Mod

    würdest Du Dich doch nicht mit dem ersten Link zufrieden geben und noch ein paar weitere aufrufen, um Dir ein Gesamtbild zu machen ...

    Und wo ist der nächste Link? Der Rest der Google-Ergebnisse (außer vllt. dem) ist wertlos. Außerdem beherrsche ich die deutsche Sprache, und weiß sehr gut, was frickelig heißt. Dazu brauche ich keine Bestätigung von irgendeinem Online-Wörterbuch. (Können wir diese merkwürdige OT-Diskussion nun bitte beenden?)

    Dass es Dir da gar nicht drum ging, hab ich mir zwar gedacht, aber ich wollte nichts in Dein Posting hineininterpretieren und hab es deshalb so genommen, wie es dort stand - so gut ich konnte, jedenfalls.

    Nun, jetzt weißt du es - ich habe lediglich SeppJ widersprechen wollen. 🙂



  • Du kannst die Datei natuerlich auch gleich von hinten oeffnen.

    ifstream input;
    input.open("Example.txt", ios::ate);
    unsigned int ctr = input.tellg();
    input.close();
    

    Ansonsten fuer Windows kriegst du hier die Filesize raus.
    http://msdn.microsoft.com/en-us/library/windows/desktop/aa365739(v=vs.85).aspx



  • Arcoth schrieb:

    Und wo ist der nächste Link?

    Mhm, vielleicht hab ich Dich doch überschätzt?
    Aber einmal helfe ich Dir noch:
    Ohne das jetzt selbst überprüft zu haben, behaupte ich mal, er ist direkt unter dem ersten.


  • Mod

    Das reicht jetzt. Ich werde hier nicht meine Zeit damit verschwenden, dir irgendwas zu beweisen.

    ifstream input;
    input.open("Example.txt", ios::ate);
    

    Den Konstruktor von ifstream nicht ignorieren.

    ifstream input("Example.txt", ios::ate);
    

    Schließen muss man die Datei auch nicht, das macht der Destruktor. Und statt unsigned int den richtigen Typ nehmen.



  • Arcoth schrieb:

    Das reicht jetzt. Ich werde hier nicht meine Zeit damit verschwenden, dir irgendwas zu beweisen.

    ifstream input;
    input.open("Example.txt", ios::ate);
    

    Den Konstruktor von ifstream nicht ignorieren.

    ifstream input("Example.txt", ios::ate);
    

    Schließen muss man die Datei auch nicht, das macht der Destruktor. Und statt unsigned int den richtigen Typ nehmen.

    Hi,
    was ist denn der richtige Datentyp fuer tellg?

    Ouf overflow habe ich das dazu gefunden: http://stackoverflow.com/questions/10065323/how-to-collect-and-store-tellp-tellg-return-types

    Was den Konstruktor angeht ist doch der einzige Unterschied zwischen deinem Objekt zu meinem, dass ich das ifstream-Objekt nicht gleich mit einer Datei assoziiere, oder?

    Ich habe irgendwo gelesen, dass man sobald man mit einer Datei fertig ist sie so schnell wie moeglich wieder schliessen soll. Der Destruktor des ifstream Objektes wird ja erst aufgerufen, wenn das Objekt "out of scope" gegangen ist.

    Oder brauch ich mir die Muehe nicht machen?



  • Vielen Dank für die vielen Antworten.

    Ich habe jetzt

    ifstream file( "example.txt", ios::binary | ios::ate);
    return file.tellg();
    

    übernommen.

    Wie kann ich denn nun aber diesen Wert einer Variablen zuweisen?



  • Ich muss mich korrigieren. Diese Lösung scheint nicht zu funktionieren.

    Sobald ich

    ifstream file( source_file );
    

    durch

    ifstream file( source_file, ios::binary | ios::ate );
    	return file.tellg();
    

    ersetze, stürzt das Programm an der Stelle ab.


  • Mod

    djnforce schrieb:

    ersetze, stürzt das Programm an der Stelle ab.

    Das kann hunderte Ursachen haben. Siehe:
    http://www.c-plusplus.net/forum/304133

    Wie kann ich denn nun aber diesen Wert einer Variablen zuweisen?

    😕 Was hast du vor? Kannst du überhaupt C++?



  • Ich bin C++ Anfänger.

    Ich habe eine Textdatei mit über 10 000 Zeilen, aus der ich nur bestimmte Zahlen benötige.
    Diese werden untereinander in einer anderen Textdatei gespeichert. Das funktioniert super.

    Das ganze dauert aber ca. 1-2 Minuten und ich möchte den Nutzer nicht im ungewissen über den Fortschritt lassen.

    Deshalb möchte ich zu Anfang gerne wissen, wie viele Character die Ausgangsdatei hat um diese Zahl mit der zur Zeit durchsuchten Anzahl an Character zu vergleichen.

    So kann ich dann immer ausgeben lassen:
    10% 20% usw.

    Der gesamte Code:

    // This program will find specific information in the huge tripfile.
    // If you have some questions please feel free to ask ...
    // build: 13.11.2013
    
    #include <fstream>
    #include <string>
    #include <iostream>
    #include <iterator>
    #include <sstream>
    #include <math.h>
    #include <stdio.h>
    
    using namespace std;
    
    // "ignore_until" forces to ignore all words until a specific word is found
    
    void ignore_until(istream& is, const string& delim)
    {
    	string data;
    
    	while (is.good())
    	{
    		data.push_back((char) is.get());
    
    			if (data.find(delim) != string::npos) return;
    	}
    }
    
    int main()
    {
    	string source_file;
    	string target_file;
    	int opt;
    	float size;
    
    	cout << "Please choose one option:\n\n1- GPS coordinates \n2- GPS coordinates & fieldstrengths \n3- GPS coordinates & fieldstrengths & frequencies \n4- GPS coordinates & fieldstrengths & frequencies & Programm Identification\n";
    	cin >> opt;
    
    	cout << "\n\nsource file (example.txt):" << endl;
    	cin >> source_file; // type name of source file
    
    	cout << "\ntarget file (further_example.txt):" << endl;
    	cin >> target_file; // type name of target file
    
    	cout << "\nmerging still in progress (it may take a few minutes), please wait..." << endl;
    
    	ifstream file( source_file );
    	//size = file.tellg();
    
        if( !file.is_open() ) // could the file be opened?
            return -1;
    
        ofstream new_file( target_file ); // In this file we would like to save our data
        new_file.setf(ios::fixed); // no scientific output
    
    	// what we searching for:
    
    	const string what_reference = "<proxyf"; // Our search will start at the head of our source file
        const string what_coord = "Coord:(";					// we are looking for GPS coordinates
    	const string what_field = "Fieldstrength         : "; // we are looking for FM Fieldstrength
    	const string what_freq = "Frequency             : "; // we are looking for related frequency
    	const string what_pi = "PI                    : "; // PI --> Program Identification. Is a unique number for each radio station. You can check which station name is behind the number under http://www.fmlist.org (click on "continue as guest")
    
        string str; // do we need to check if we are starting in the head of the file
    
        for(char c; file.get(c);) // each time the loop pass we read one character
        {
            str += c; // This character we attach to the string 
    
    		if( str == what_reference ) // if this string matches the variable "what_reference" we know that we are in the file header and can start to read
            {
    			//#### read coordinates
    
    			ignore_until(file, what_coord); // ignore everything until "what_coord" appears
    
                double x;
                file >> x; // read first coordinate
    
                file.ignore( 1 ); // Ignore the comma
    
    			double y;
                file >> y; // read second coordninate
    
    			//#### read frequency
    
    			ignore_until(file, what_freq); // ignore everything until "what_freq" appears
    
    			double freq; 
    			file >> freq; // read frequency
    
    			//#### read PI --> Program Identification. Is a unique number for each radio station. You can check which station name is behind the number under http://www.fmlist.org (click on "continue as guest")
    
    			ignore_until(file, what_pi); // ignore everything until "what_pi" appears
    
    			string pi;
    			file >> pi; // read PI
    
    			//#### read fieldstrenth
    
    			ignore_until(file, what_field);// ignore everything until "what_field" appears
    
    			string value;
    			file >> value; // read fieldstrength
    
    			// write data to file
    
                if( file ) // was reading successful ?
    
                {	// reading was successful --> write data to file while recalculating coordinates (coordinate transformation)
    				if ( opt == 4 )
    					new_file << y * (360 / pow(2,32)) << ',' << x * (360 / pow(2,32)) << ',' << value << ',' << freq*0.001 << ',' << pi << '\n'; 
    				else
    				if ( opt == 3 )
    					new_file << y * (360 / pow(2,32)) << ',' << x * (360 / pow(2,32)) << ',' << value << ',' << freq*0.001 << '\n'; 
    				else
    				if ( opt == 2 )
    					new_file << y * (360 / pow(2,32)) << ',' << x * (360 / pow(2,32)) << ',' << value << '\n'; 
    				else
    				if ( opt == 1 )
    					new_file << y * (360 / pow(2,32)) << ',' << x * (360 / pow(2,32)) << '\n'; 
                }
    
                str.clear(); // we clear str and start again
            }
    
            else if( str.length() == what_coord.length())
            {
                // its necessary, don't ask why :-)
                str.erase( 0, 1 );
            }
    
    	}
    
    }
    

  • Mod

    djnforce schrieb:

    Das ganze dauert aber ca. 1-2 Minuten und ich möchte den Nutzer nicht im ungewissen über den Fortschritt lassen.

    😮 Das sollte eine Sache von Sekundenbruchteilen sein. Unwahrnehmbar schnell. Tausende Zeilen, selbst wenn die Zeilen tausende Zeichen lang sind, sind absolut gar nichts für einen Computer. Du machst sicherlich etwas furchtbar falsch. Hier sollte der Ansatz zur Verbesserung liegen.

    Ich habe eine Textdatei mit über 10 000 Zeilen, aus der ich nur bestimmte Zahlen benötige.

    Sicher, dass C++ hier das richtige Mittel ist? Das klingt nach einem Einzeiler für Konsolentools wie grep.

    Irgendwie kommt es mir so vor, als hätte ich das schon einmal geschrieben. *such* Hier:
    http://www.c-plusplus.net/forum/p2362383#2362383

    Zu deinem Code: Das sieht ungeheuer umständlich aus. Man liest nicht einzelne Zeichen, wenn man nicht muss. Man vergleicht nicht nach jedem Zeichen, wenn man nicht muss. Außerdem passt der Kontrollfluss deines Programms nicht zu dem, was du im anderen Thread als Aufgabe beschrieben hast, das Programm sollte nicht korrekt funktionieren. Du hast den Code abgeschrieben und verändert, ohne ihn zu verstehen, oder?

    Wenn es schon C++ für diese Aufgabe sein soll, dann lies doch einfach alles in einem Rutsch ein (oder in großen Blöcken) und durchsuch die Blöcke nach den Schlüsselwörtern. Etwas anderes macht grep übrigens auch nicht, weshalb das am Ende gleich schnell sein sollte (und im Zweifelsfall ist dein Programm langsamer, da grep ziemlich flott ist und du wahrscheinlich irgendwelche Fehler machst).



  • Ja das ist richtig. Ihr habt mir hier schonmal sehr geholfen.

    Ich habe jetzt aber eine Lösung für mein Problem:

    // data size
    	ifstream file1( source_file, ifstream::in | ifstream::binary );
    	file1.seekg(0, ios::end);
    	int fileSize = file1.tellg();
    	file1.close();
    
    	cout << fileSize << endl;
    

    Damit kann ich arbeiten 🙂

    Das Programm soll nicht perfekt sein. Es muss nur funktionieren...


Log in to reply