C++ Dateien in Ordner finden, zählen, aussortieren und dem Alter nach ordnen

Baal Netbeck schrieb:
Ich wollte sie als Vektor speichern, aber ich kann keinen vektor
Code:
vektor <std::filesystem::file_time_type> ftimev;
erstellen....
...
dir ist schon klar, dass die Klasse vector mit c geschrieben wird?

Hier die 3 grundlegenden Möglichkeiten den Vektor zu erstellen:

C++:
#include <filesystem>
#include <vector>

int main(){

    auto val = std::filesystem::last_write_time(std::filesystem::path("some path"));

    //Variant 1
    std::vector<std::filesystem::file_time_type> ftimev1;

    //Variant 2
    std::vector<
        std::chrono::time_point<
            std::filesystem::file_time_type::clock>> ftimev2;

    //Variant 3
    std::vector<decltype(val)> ftimev3;
    
    ftimev1.push_back(val);
    ftimev2.push_back(val);
    ftimev3.push_back(val);

}
https://godbolt.org/#g:!((g:!((g:!(...:0,t:'0')),l:'2',n:'0',o:'',t:'0')),version:4
 
  • Gefällt mir
Reaktionen: Baal Netbeck
new Account() schrieb:
dir ist schon klar, dass die Klasse vector mit c geschrieben wird?
eigentlich ja...Tippfehler. ;)

Danke an Alle!! :)

Ich glaube dann habe ich jetzt alles.

Ich habe Dateiname und Zeitstempel in Vektoren.....sortiert bekomme ich die schon irgendwie und an der Abfrage ob es .csv dateien sind, bin ich gerade dabei......da bin ich zuversichtlich. :)

Edit....das erkennen von csv geht jetzt auch.....jetzt noch sortieren....
 
Zuletzt bearbeitet:
  • Gefällt mir
Reaktionen: Balkoth
.......es hat dann doch noch 2 Tage gedauert....viele komische Probleme...warum kann ich die file_time_type zwar in einem Cout als Anzahl der Sekunden nach epoch ausgeben, aber nicht in eine int konvertieren?
...jetzt konvertiere ich sie gar nicht und man kann sie auch so vergleichen.

....Leerzeichen sind mein neuer Todfeind....für die Dateipfade und namen muss ich sie auslesen....das ging gut..aber für das einlesen der Zeilen bin ich in Probleme gekommen, da zwar getline die Leerzeichen ausliest, aber das übertragen des sstringstreams in einen String bei jedem Leerzeichen abbricht:grr:....alle Lösungen die ich dazu finden konnte haben entweder gar nichts bewirkt(oder nicht compilliert) oder haben alles vor dem Leerzeichen gelöscht....Am Ende habe ich noch vor dem Stringstream die Leerzeichen aus dem einlesestring löschen können.:cheerlead:

Mit Vektoren und diesen iteratorn komme ich auch nicht gut klar.....mit push_back verliert man den überblick wie groß der jetzt ist und dann hatte ich Fehler weil ich auf nicht vorhandene Einträge zugreifen wollte.

Dann habe ich noch das Einlesen versucht so automatisch wie möglich zu halten und nachträglich etwas anpassungsfähig zu bleiben.
Also braucht man nicht vorzugeben, ob es Frametimedateien von Fraps, OCAT oder CapFrameX sind....anhand des ersten Eintrags wird erkannt, was es für ein typ ist und dementsprechend weiß das Programm, in welcher Zeile und Spalte die Zeiten der Frames stehen.
Damit man nachträglich darauf reagieren kann, habe ich in dem Ordner noch eine extradatei mit Settings erstellt, in der man das Keywort oder die Position der Daten anpassen könnte...hat man die Datei nicht, wird ein Standardset verwendet....auch eine reihe weiterer Optionen kann man durch anpassen der Datei wählen und muss es nicht bei jedem start über ein cin auswählen....nur den Pfad des Ordners mit den Daten muss natürlich angegeben werden.

Im Moment muss noch darauf geachtet werden, dass es keine anderen csv dateien im Ordner gibt.....eventuell pflege ich irgendwann ein, dass er die dann automatisch übergeht...aber den Inhalt prüfe ich erst nachdem die Dateien sortiert sind und da wäre es blöd nachträglich nochmal zu suchen und zu sortieren.

Der Rest vom Code ist jetzt leider nicht mehr kompatibel, da ich die Variablen geändert habe und ich noch vieles bei der Gelegenheit verbessern möchte.

...die Performance ist im Moment noch grausig.......keine Ahnung warum, aber mit meinem alten einlesecode hatte ich eigentlich alles ruckzuck eingelesen und sogar schon verarbeitet.....da kann ich mich am Ende ja noch drum kümmern.

vermutlich kann ich auch einiges am code einfach weglassen....all die Überreste von meinen Versuchen Dies und Das zu erreichen.....auch bei den include Sachen kann ich bestimmt einiges weglassen......aber besser zu viel eingebunden haben und nich brauchen, als es dann zu brauchen und nichtmehr zu wissen welches include man dafür braucht.

hier erstmal der code bis die Zeitpunkte der Frames und die Frametimes in die jeweiligen arrays gespeichert wurden.
C++:
//#include "pch.h"
#include <iostream>
#include <fstream>
#include <string>
#include <math.h>
#include <stdio.h>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>
#include <complex>
#include <valarray>
#include <stdlib.h>
#include <cstring>
#include <chrono>
#include <iomanip>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <vector>
#include <iterator>
#include <filesystem>

#pragma comment(lib, "User32.lib")

using namespace std;
//using fs = std::filesystem;
namespace fs = std::filesystem;
using namespace std::chrono_literals;

string input = "";
string ordner, valid_ordner, endung;
string path;
int  x, Zeilen[16], frametimezahl[16], frapstrue[16], csvdaten = 0, datenanzahl, Frametimezahl[16], anz_zu_verarbeiten = 0, OriginPro = 0, Autokorrelation = 0, Einlesepunkte[4][3], Ordnerfragen = 0;


string s = "", namen = "default", keywort_fraps = "Frame", keywort_OCAT = "Application", keywort_CapFrameX = "//GameName=", Frametimedatennamen[16];

double framezeit[16][790000], frametimes[16][790000];


ifstream csvread;
fstream csvout;

vector<string> pfad, dateinamenv, endungv, endungvx, wegwerfvektor;
vector <std::filesystem::file_time_type> filetimev;
vector<string> filenamev, filenemevsortiert;

template<class T> std::string toString(const T& t)//Buchstabensalat zu wörtern machen.....
{
    std::ostringstream stream;
    stream << t;
    return stream.str();
}

template<class T> T fromString(const std::string& s)
{

    std::istringstream stream(s);
    T t;
    stream >> t;

    return t;
}
template<char delimiter>
class WordDelimitedBy : public std::string
{};


std::filesystem::file_time_type last_write_time(const std::filesystem::path& p);

template<class Rep, class Period = std::ratio<1>> class duration;

vector<string> split(const string& s, const char trenner)// liest einen String s ein(trenner habe ich ignoriert weil es Probleme mit \ gab), und trennt ihn bei jedem \ ...die getrennten Teile landen in einem Vektor...komischerweise werden \\ wie \ behandelt
{
    vector<string> tokens;//Ergebnisvektor
    string token; //einzelstrings zwischen den trennern
    istringstream tokenStream(s); // datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++
    while (getline(tokenStream, token, '\\')) // getline weil es auch Leerzeichen einlesen können soll
    {
        tokens.push_back(token);
        ordner = token;// am Ende bleibt der letzte Abschnitt übrig...also der Ordner der eingelesen werden soll

    }
    return tokens;
}

vector<string> split2(const string& s, const char trenner)// liest einen String s ein, und trennt ihn bei jedem punkt ...die getrennten Teile landen in einem Vektor
{
    vector<string> tokens;//Ergebnisvektor
    string token;//einzelstrings zwischen den trennern
    istringstream tokenStream(s);// datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++\frametime1.csv
    while (getline(tokenStream, token, '.'))
    {
        tokens.push_back(token);
        endung = token; // Am Ende sollte der letzte Abschnitt und damit die Endung der Datei stehen bleiben
    }
    return tokens;
}

vector<string> split3(const string& s, const char trenner)// liest einen String s ein, und trennt ihn bei jedem komma ...die getrennten Teile landen in einem Vektor
{
    vector<string> tokens;//Ergebnisvektor
    string token;//einzelstrings zwischen den trennern
    istringstream tokenStream(s);// datenstream der z.B. so aussehen soll: C:\Users\Bhaal\Desktop\C++\frametime1.csv
    while (getline(tokenStream, token, ','))
    {
        tokens.push_back(token);
        endung = token; // Am Ende sollte der letzte Abschnitt und damit die Endung der Datei stehen bleiben
    }
    return tokens;
}

void Settings_einlesen()  //Settinganpassungen laden
{

    csvread.open("Frametimesettings_mit exe in einem Ordner halten.txt", ios::in);
    double d;
    int zeile = 0;
    Einlesepunkte[1][1] = 2;//standardwerte vorgeben falls die Datei nicht gefunden wurde;
    Einlesepunkte[1][2] = 1;
    Einlesepunkte[2][1] = 2;
    Einlesepunkte[2][2] = 11;
    Einlesepunkte[3][1] = 18;
    Einlesepunkte[3][2] = 11;
    Ordnerfragen = 0;
    if (csvread) {

        cout << "Frametimesettings werden eingelesen." << endl;
        while (getline(csvread, s))//Datei zeilenweise  einlesen
        {
            const string input = s;
            istringstream stm(input);
            string str;
            stm >> str;
            if (zeile == 2) {
                d = fromString<double>(str);
                anz_zu_verarbeiten = d;//Anzahl der verarbeiteten csv Dateien (0 auto(bis zu 16), 1, 3, 5, 8, 16)
            }
            if (zeile == 4) {
                d = fromString<double>(str);
                OriginPro = d;//Ausgabedatei für Origin Pro erzeugen (0 ja, 1 nein)
            }
            if (zeile == 6) {
                d = fromString<double>(str);
                Autokorrelation = d;//experimentelle Autokorrelation der Framtimeverläufe (0 ja, 1 nein)
            }
            if (zeile == 8) {
                keywort_fraps = str;//string bis zum ersten , in einer Fraps Frametimedatei
            }
            if (zeile == 10) {
                d = fromString<double>(str);
                Einlesepunkte[1][1] = d;//erste Zeile mit Daten in einer Fraps Frametimedatei
            }
            if (zeile == 12) {
                d = fromString<double>(str);
                Einlesepunkte[1][2] = d;//Anzahl , vor dem Zeitstempel der Frames in einer Fraps Frametimedatei
            }
            if (zeile == 14) {
                keywort_OCAT = str;//string bis zum ersten , in einer OCAT Frametimedatei
            }
            if (zeile == 16) {
                d = fromString<double>(str);
                Einlesepunkte[2][1] = d;//erste Zeile mit Daten in einer OCAT Frametimedatei
            }
            if (zeile == 18) {
                d = fromString<double>(str);
                Einlesepunkte[2][2] = d;// Anzahl, vor dem Zeitstempel der Frames in einer OCAT Frametimedatei
            }
            if (zeile == 20) {
                keywort_CapFrameX = str;//string bis zum ersten , in einer CapFrameX Frametimedatei
            }
            if (zeile == 22) {
                d = fromString<double>(str);
                Einlesepunkte[3][1] = d;//erste Zeile mit Daten in einer CapFrameX Frametimedatei
            }
            if (zeile == 24) {
                d = fromString<double>(str);
                Einlesepunkte[3][2] = d;//Anzahl , vor dem Zeitstempel der Frames in einer CapFrameX Frametimedatei
            }
            if (zeile == 26) {
                d = fromString<double>(str);
                Ordnerfragen = d;//Programmordner einlesen (0 nein, 1 ja)
            }
            zeile = zeile + 1;
        }

        csvread.close();

    }
    else {
        cerr << "Fehler beim Lesen der Settings Datei....Standard wird verwendet!" << endl;
    }
}


void ordnerlesen()
{
    int i, end = pfad.size(); //Länge ermitteln bevor ich damit rumspiele
    for (i = 0; i < end - 1;)//den path aus den einzelbausteinen zusammensetzen
    {
        path = path + pfad[i] + "\\";
        i++;
    }
    path = path + pfad[end - 1];//letztes Element hat kein backslash dahinter

    std::filesystem::file_time_type ftime[1024];//es sind hoffentlich nicht mehr als 1024 Dateien in dem Ordner
    i = 0;
    for (const auto & entry : std::filesystem::directory_iterator(path))//der iterator durchforstet den ordner mit dem pointer entry??
    {

        ftime[i] = std::filesystem::last_write_time(entry);//letztes änderungsdatum erfassen

        //std::cout << entry.path() << std::chrono::duration_cast<std::chrono::seconds>(ftime[i].time_since_epoch()).count() << std::endl;
        filenamev.push_back(entry.path().string());//den Pfad mit dateinamen als string in einen Vektor schieben
        filetimev.push_back(ftime[i]);// die änderungsdaten in einen Vektor schieben....der hat ein spezielles Format dafür

        //cout << filenamev[i] << endl;
        i++;
    }

    end = i; datenanzahl = i; //jetzt ist end die Anzahl der gefundenen einträge
    i = 0;
    while (i < end) { //einträge durchsuchen
        endungvx = split2(filenamev[i], '.'); // Hilfsvektor, der den aktuellen Dateinamen nach punkt trennt und die globale variable "endung" setzt
        endungv.push_back(endung);//speichert die Endung in einen Vektor
        //cout << endung << endl;
        if (endung == "csv") { csvdaten++; }// damit wir wissen, wie viele einträge csv Dateien sind
        i++;
    }//cout << "csvdings" << csvdaten << endl;
}

void filesotieren()// Die Dateien im Ordner werden durchsucht und die csv dateien dem alter nach in "filenamevsortiert" gespeichert...csvdaten enthält die Anzahl der gefundenen csv dateien
{
    const auto p0 = std::chrono::time_point<std::chrono::system_clock>{};//irgendwie für epoch nötig
    std::time_t epoch_time = std::chrono::system_clock::to_time_t(p0); //epoch zeit setzen

    //const auto p1 = std::chrono::system_clock::now();
    //const auto p2 = p1 - std::chrono::hours(24);
    int i = 0, j = 0;
    int biggernummer = 0; // und die nummer der ältesten Datei zwischenzuspeichern
    std::filesystem::file_time_type bigger; // um die jeweils ältesten Zeitstempel zwischenzuspeichern

    int gefunden = 0;
    const auto sz = datenanzahl;
    i = 0;
    while (i < sz) {//n*n schleife um alle Dateien zu vergleichen.
        gefunden = 0; j = 0;

        //std::filesystem::last_write_time(string_to_path(filename[j]), last_write_time(filename[j]) -350000h);  //bigger zurück stellen
        while (j < sz)
        {

            if (endungv[j] == "csv") {//nur csv dateien vergleichen
                //cout << "i " << i << " j " << j << "time" << std::chrono::duration_cast<std::chrono::seconds>(filetimev[j].time_since_epoch()).count() << endl;
                if (filetimev[j] > bigger)//gucken ob der aktuelle Zeitstempel größer ist als der bisher gefundene
                {

                    bigger = filetimev[j];//Wert des größten merken
                    biggernummer = j;// position des größten merken
                    gefunden = 1;//setzen, dass es einen Fund gab
                }
            }j++;
        }
        if (gefunden == 1) {// wenn es einen Fund gab
            //cout << "gefunden i " << i << " j " << biggernummer << "time" << std::chrono::duration_cast<std::chrono::seconds>(filetimev[biggernummer].time_since_epoch()).count() << endl;
            filenemevsortiert.push_back(filenamev[biggernummer]);//den filenamen(ist glaube ich der komplette Pfad) in den sortierten verktor einfügen
            endungv[biggernummer] = "ex_csv";//die Endung ändern, damit dieser Wert kein weiteres Mal gefunden wird
            bigger = bigger - 350000h;

            //cout << "csvdings" << csvdaten << endl;
        } i++;
    }
    i = 0;
    cout << endl << "Nach dem Alter sortiert: " << endl;
    while (i < csvdaten) {//da die Daten jetzt die neueste datei zuerst im Vektor haben, ich aber mit der ältesten anfangen möchte, tausche ich sie durch und nehme maximal 16 Dateien
        if (i <= 15) {
            Frametimedatennamen[i] = filenemevsortiert[csvdaten - i - 1];//älteste csv datei zuerst in das array
            cout << Frametimedatennamen[i] << endl;
        }
        i++;
    }
}

void dateizaehlen_identifizieren(int i)
{
    wegwerfvektor = split(Frametimedatennamen[i], ',');//mache ich nur, weil ich nochmal den string "ordner" neu setzen möchte
    string dateipfad = path + "\\" + ordner;
    //cout << " pfad zum oeffnen" << dateipfad << endl;
    csvread.open(dateipfad, ios::in);
    Zeilen[i] = 0;//hier steht nachher wie viele Zeile die Dateien hatten
    int eintraege = 0;
    vector<string> zeileneintraege;


    if (csvread) {
        //Datei bis Ende einlesen und bei ';' strings trennen
        cout << "Frametimedatei:" << i + 1;
        while (getline(csvread, s))
        {
            const string inhalt = s;
            istringstream stm(inhalt);
            string str;
            stm >> skipws >> str;
          
            if (eintraege == 0) {
                zeileneintraege = split3(str, ',');//die eingelesenen Zeile nach komma in strings trennen
                //cout << "Frapstest" << zeileneintraege[0] << endl;
                if (zeileneintraege[zeileneintraege.size() - 1] == "Frame") { frapstrue[i] = 1; }//Ist eine Frametimedatei von Fraps
          
                //cout << "Frapstest" << zeileneintraege[0] << endl;
                if (zeileneintraege[0] == "Application") { frapstrue[i] = 2; }//Ist eine Frametimedatei von OCAT
          
                //cout << "Frapstest" << zeileneintraege[0] << endl;
                if (zeileneintraege[0] == "//GameName=") { frapstrue[i] = 3; }//Ist eine Frametimedatei von CapFrameX
            }
//cout << frapstrue[i] << endl;
            eintraege = eintraege + 1;
        }
        csvread.close();
        if (frapstrue[i] == 0) // es wurde kein Keywort beim einlesen entdeckt
        {
            cout << ordner << " ist keine bekannte csv Frametime-Syntax." << endl; cin >> s; exit(0);
        }
        if (frapstrue[i] == 1) { cout << " ist eine Fraps-Frametime-Syntax"; }
        if (frapstrue[i] == 2) { cout << " ist eine OCAT-Frametime-Syntax"; }
        if (frapstrue[i] == 3) { cout << " ist eine CapFrameX-Frametime-Syntax"; }
    }
    else {
        cerr << "Fehler beim Lesen!" << endl; csvread.close(); cin >> s; exit(0);
    }
    Zeilen[i] = eintraege;
    if (Zeilen[i] > 790000)// im Moment noch meine Beschränkung der arrays in die ich die Daten speichere
    {
        cout << "Datei ueberschreitet die Maximalgroeße von 790000 Zeilen!";
        cin >> s;
        exit(0);
    }
    if (Zeilen[i] < 50)//entweder ist die Datei keine Frametimedatei oder zu klein um sinnvoll ausgewertet zu werden
    {
        cout << "Datei zu klein!";
        cin >> s;
        exit(0);
    }
    cout << " und hat: " << Zeilen[i] << " Zeilen" << endl;
}

void dateilesen(int i)
{
    wegwerfvektor = split(Frametimedatennamen[i], ',');
    string dateipfad = path + "\\" + ordner;
    //cout << " frapstrue" << frapstrue[i] << endl;
    csvread.open(dateipfad, ios::in);

    int eintraege = 0, temp1, temp2, framezahl = 0, frametyp = frapstrue[i];
    vector<string> zeileneintraege;
    double startzeit, tempzeit, tempzeit2, teiler1, teiler2;
    if (frapstrue[i] == 1) { teiler1 = 1.0; teiler2 = 100.0; }
    if (frapstrue[i] == 2) { teiler1 = 100.0; teiler2 = 1.0; }
    if (frapstrue[i] == 3) { teiler1 = 100.0; teiler2 = 1.0; }
    temp1 = Einlesepunkte[frametyp][1];
    temp2 = Einlesepunkte[frametyp][2];
    //cout << Einlesepunkte[1][1] << endl;
    //cout << Einlesepunkte[1][2] << endl;
    //cout << Einlesepunkte[2][1] << endl;
    //cout << Einlesepunkte[2][2] << endl;
    //cout << Einlesepunkte[3][1] << endl;
    //cout << Einlesepunkte[3][2] << endl;
    //cout << frapstrue[i] << endl;
    //ios_base::fmtflags (skipws);
    if (csvread) {

        cout << "Werte aus " << "Frametimedatei: " << i + 1 << " werden in ein array gespeichert..." << endl;

        while (getline(csvread, s)) {
            string inhalt = s;
            inhalt.erase(remove(inhalt.begin(), inhalt.end(), ' '), inhalt.end());//wenn ich nicht die Leerzeichen entferne, übergibt der istringstream dem String "str" nur die Zeile bis zum ersten Leerzeichen...die Framezeiten stehen aber dahinter
            istringstream stm(inhalt);
            string str;
            stm >> ws >> str;
            zeileneintraege = split3(str, ',');//die eingelesenen Zeile nach komma in strings trennen

            if (eintraege >= temp1)//startet nicht beim ersten eintrag, da dieser manchmal falsch gemessen wird
            {
                if (eintraege < (Zeilen[i] - 2)) //hört kurz vor dem Ende auf
                {
                    //double n;

                    double d = fromString<double>(zeileneintraege[temp2]);
                    //cout << d << endl;
                    if (eintraege == temp1) {
                        startzeit = d; framezeit[i][0] = (d - startzeit) / teiler2;//beim zweiten Frame anfangen und ihn auf null setzen...startzeit ist dabei in der Einheit wie d...die Daten im Array sollen Sekunden für die Zeiten und ms für die frametimes sein
                    }
                    if (eintraege > temp1) {
                        tempzeit = (d - startzeit) / teiler2;
                        framezeit[i][eintraege - temp1] = tempzeit;//Zeitpunkte der Frames eintragen
                        tempzeit2 = tempzeit - framezeit[i][eintraege - temp1 - 1];
                        frametimes[i][eintraege - temp1 - 1] = tempzeit2;//rückwirkend den Unterschied der Zeitpunkte als Frametime in den vorheringen Frame speichern
                        framezahl++;


                    }
                }

            }
            eintraege = eintraege + 1;
        }
        frametimezahl[i] = framezahl;
        csvread.close();
    }
    else {
        cerr << "Fehler beim Lesen!" << endl;
    }
    //cout << zeile1 << endl;
}
int main() {
    cout.precision(4);//damit Zahlen nicht zu viele Nachkommastellen bei der ausgabe haben
    int i, auswahl;//bald nicht mehr nötig
    Settings_einlesen();
    //cin.ignore();//irgendwie wichtig
    if (Ordnerfragen == 0) {
        cout << "Please enter a valid location with Fraps or OCAT/CapFrameX Frametimes files (.csv) like: C:\\Fraps\\Benchmarks" << endl;
        getline(cin, input);//kann auch eingaben mit Leerzeichen einlesen
        cout << "You entered: " << input << endl;
        cin.clear();//irgendwie wichtig

        if (std::filesystem::is_directory(input)) { std::cout << "it is the valid directory: "; }
        else { std::cout << "it is not a valid directory." << endl; }//testen ob die Eingabe auch ein Verzeichnis ist
    }
    else { input = std::filesystem::current_path().string(); }

    pfad = split(input, ','); // das Verzeichnis nach \ trennen(das Komma ist nur ein Platzhalter, da \ Problemem gemacht hat)
    cout << ordner << endl;
    valid_ordner = ordner;

    ordnerlesen();//ordner wird eingelesen und die Namen, Zeiten und Endungen der Dateien in Vektoren gespeichert

    filesotieren();// die gefundene csv Dateien werden dem alter nach sortiert und in ein array gespeichert.

    for (i = 0; i < 16;)//Schleife um die Inhalte einzulesen
    {
        dateizaehlen_identifizieren(i);
        dateilesen(i);
        i++;
    }
    cout << "Frametimes eingelesen und bereit zur weiterverarbeitung....." << endl;
    cin >> x;
    return 0;

}
Keine Ahnung ob ihr euch das angucken wollt....ich habe versucht durchaus kommentare in den code zu schreiben....ob man versteht, was ich gemacht habe...keine Ahnung . ;)

Wenn sich das jemand anguckt, kann er mir ja mal ne Rückmeldung geben ob es bei ihm funktioniert.
Ergänzung ()

Was ist eigentlich das Problem mit #include "pch.h"?

Ich hatte mein altes Projekt abgeändert und da stand es drin....und hat keine Probleme gemacht.....dann habe ich nur den neu programmierten Teil des codes rausgefischt....in ein neues Programm kopiert weil ich wissen wollte, ob es "standalone" funktioniert(damit ich es hier posten kann), aber dann wurde die Datei nichtmehr gefunden....ich dachte das wäre so ein Standard, den jedes Programm drin hat??
 
Zuletzt bearbeitet:
Baal Netbeck schrieb:
warum kann ich die file_time_type zwar in einem Cout als Anzahl der Sekunden nach epoch ausgeben, aber nicht in eine int konvertieren?
C++:
std::filesystem::file_time_type timestamp;
int elapsedTime = static_cast<int>(timestamp.time_since_epoch().count());
Du solltest zwar kein int verwenden, weil das (angenommen int = int32_t) nur noch bis 2038 die time since epoch Platz hat. Nimm long long dann hast du keine Probleme.

Baal Netbeck schrieb:
....Leerzeichen sind mein neuer Todfeind....für die Dateipfade und namen muss ich sie auslesen....das ging gut..aber für das einlesen der Zeilen bin ich in Probleme gekommen, da zwar getline die Leerzeichen ausliest, aber das übertragen des sstringstreams in einen String bei jedem Leerzeichen abbricht:grr:....alle Lösungen die ich dazu finden konnte haben entweder gar nichts bewirkt(oder nicht compilliert) oder haben alles vor dem Leerzeichen gelöscht....Am Ende habe ich noch vor dem Stringstream die Leerzeichen aus dem einlesestring löschen können.
Du machst auch wirklich sehr komische Sachen:
C++:
string inhalt = s;
inhalt.erase(remove(inhalt.begin(), inhalt.end(), ' '), inhalt.end());
istringstream stm(inhalt);
string str;
stm >> ws >> str;
Du entfernst alle Leerzeichen, damit du dann mit dem stringstream alle leading whitespaces entfernen kannst? Was?!

Baal Netbeck schrieb:
Mit Vektoren und diesen iteratorn komme ich auch nicht gut klar.....mit push_back verliert man den überblick wie groß der jetzt ist und dann hatte ich Fehler weil ich auf nicht vorhandene Einträge zugreifen wollte.
C++:
std::vector<int> numbers;
numbers.push_back(1);
numbers.push_back(2);
numbers.push_back(3);
std::cout << "Vector size: " << numbers.size() << std::endl;
Und jetzt? Warum sollte man den Überblick verlieren? Dein Vektor speichert immer genau size() Elemente.

Baal Netbeck schrieb:
vermutlich kann ich auch einiges am code einfach weglassen....all die Überreste von meinen Versuchen Dies und Das zu erreichen.....auch bei den include Sachen kann ich bestimmt einiges weglassen......aber besser zu viel eingebunden haben und nich brauchen, als es dann zu brauchen und nichtmehr zu wissen welches include man dafür braucht.
Nein und nein! Du solltest dead-code entfernen und nur die notwendigen include verwenden, des macht deinen Code lesbarer, weniger fehleranfällig, und er kompiliert auch schneller.
Wenn dir ein include fehlt kannst du ganz leicht über https://en.cppreference.com herausfinden welches das ist.

Baal Netbeck schrieb:
Wenn sich das jemand anguckt, kann er mir ja mal ne Rückmeldung geben ob es bei ihm funktioniert.
Habe keine kompatiblen *.csv Dateien, aber der Code kompiliert und läuft bei mir zumindest. Auch wenn dein Code wirklich nicht sehr schön ist und es mich nicht wundert, dass du Performance-Probleme damit hast. Du machst sehr viel von Hand, das dir die standard library eigentlich abnehmen würde. Du könntest auch einen csv-Parser verwenden, anstatt das selbst zu implementieren. Ich würde schätzen, dass man das Ganze auf 200 Zeilen oder weniger reduzieren kann (Mit einer Skriptsprache geht es wahrscheinlich noch einfacher, aber du willst ja C++).

Baal Netbeck schrieb:
Was ist eigentlich das Problem mit #include "pch.h"?
Precompiled header. Verwendest du scheinbar nicht mehr. Kannst du in den Settings von deinem Visual Studio Projekt einstellen.
 
  • Gefällt mir
Reaktionen: Baal Netbeck
BlackMark schrieb:
Nimm long long dann hast du keine Probleme.
Danke....brauche ich hierfür ja jetzt nicht mehr, aber ich werde es mir merken :)
BlackMark schrieb:
Du entfernst alle Leerzeichen, damit du dann mit dem stringstream alle leading whitespaces entfernen kannst?
Das sind Überbleibsel von meinem rumprobieren....die leading WS entfernen kann ich rausnehmen....ich dachte erst, ich könnte damit alle Leerzeichen überspringen....aus "a,1 2 3,x" dann "a,123,x" machen(was ich ja wollte um zu umgehen, dass er nach dem ersten WS abbricht.......aber es scheint dann nur "2 3,x" daraus zu machen, was mir nichts hilft, weil mehrere Leerzeichen drin sind.....also das >> ws kann ich rausnehmen.
BlackMark schrieb:
Auch wenn dein Code wirklich nicht sehr schön ist und es mich nicht wundert, dass du Performance-Probleme damit hast. Du machst sehr viel von Hand, das dir die standard library eigentlich abnehmen würde.
Ich habe das Gefühl, dass ich schneller darin bin, die Sachen per Hand zu machen, da ich dann verstehe was passiert.....jedes Mal wenn ich librarys nutze, muss ich erstmal ganz viel lernen was da abläuft und was es für besonderheiten hat....welche syntax eingehalten werden muss...........das endet bei mir in viel Lesen von Definitionen, unter denen ich mir nichts vorstellen kann und die ich dann wild ausprobiere, um dann mit try and error irgendwann was hinzubekommen.........das kann 2min dauern...das kann aber auch 3h dauern.

Das mit der Performance ist nicht wirklich schlimm.....ich fürchte aber ich werde auch noch einige Leistungshungrige Optionen auswerten, sobald der Rest vom code mit dem neuen Einlesen in Einklang gebracht wurde.
Da denke ich ernsthaft über eine Parallelisierung nach.....wenn ich bis zu 16 Dateien auswerte, sollte es keine Probleme geben, die parallel zu verarbeiten....Das zusammenführen am Ende ist dann wieder seqenziell, aber es könnte schon viel Zeit sparen.

Kann man auch parallelisiert die Dateien lesen? oder kann pro Prpgramm nur ein .open offen sein?

Naja....erstmal gucken ob so alles funktioniert. ;)
BlackMark schrieb:
Habe keine kompatiblen *.csv Dateien, aber der Code kompiliert und läuft bei mir zumindest.
Das ist doch schonmal was..........ich hatte gedacht die meisten im Forum hätten aus den Comunity Benchmarks ein paar Ordner mit CapFrameX Frametimedaten.......aber wenn es bei dir kompilliert ist ja schonmal gut.
BlackMark schrieb:
Precompiled header. Verwendest du scheinbar nicht mehr. Kannst du in den Settings von deinem Visual Studio Projekt einstellen.
Was das ist, habe ich gegoogled.....aber bei einem neuen Projekt eingefügt, sagt er mir halt, dass er die Datei nicht finden kann.........was ich komisch fand, da sie von dem ursprünglichen Programm genutzt wurde und jetzt soll sie plötzlich weg sein..........deshalb habe ich sie mit den // aus dem code genommen.
 
Zuletzt bearbeitet:
Baal Netbeck schrieb:
Das sind Überbleibsel von meinem rumprobieren....die leading WS entfernen kann ich rausnehmen....ich dachte erst, ich könnte damit alle Leerzeichen überspringen....aus "a,1 2 3,x" dann "a,123,x" machen(was ich ja wollte um zu umgehen, dass er nach dem ersten WS abbricht.......aber es scheint dann nur "2 3,x" daraus zu machen, was mir nichts hilft, weil mehrere Leerzeichen drin sind.....also das >> ws kann ich rausnehmen.
Ach ja, das habe ich noch vergessen. Wenn du es schon von Hand parsen willst, dann nimm doch bitte regex, die sind mittlerweile in der C++ standard library und nehmen dir sehr viel Arbeit ab.

Baal Netbeck schrieb:
Ich habe das Gefühl, dass ich schneller darin bin, die Sachen per Hand zu machen, da ich dann verstehe was passiert.....jedes Mal wenn ich librarys nutze, muss ich erstmal ganz viel lernen was da abläuft und was es für besonderheiten hat....welche syntax eingehalten werden muss...........das endet bei mir in viel Lesen von Definitionen, unter denen ich mir nichts vorstellen kann und die ich dann wild ausprobiere, um dann mit try and error irgendwann was hinzubekommen.........das kann 2min dauern...das kann aber auch 3h dauern.
Also bei guter Dokumentation sollte es dich bei weitem nicht so viel Zeit kosten wie es von Hand zu machen. Hängt natürlich von der Library ab, aber einen csv-Parser hast du ganz schnell am Laufen, und der ist dann auch (hoffentlich) schneller, effizienter, und korrekter, als was du von Hand geschrieben hast. Du weißt dann natürlich nicht, was die Library intern macht, aber wenn es dir nicht ums lernen geht, spielt das auch keine Rolle. Wenn du natürlich etwas lernen willst, dann musst du es von Hand machen.

Baal Netbeck schrieb:
Kann man auch parallelisiert die Dateien lesen? oder kann pro Prpgramm nur ein .open offen sein?
Ja, natürlich. Wobei das Lesen der Datei nicht dein Bottleneck sein sollte, sondern deine Auswertung, die sehr ineffizient ist. Mit einem csv-Parser und sinnvoller Verwendung der standard library (container, algorithm), solltest du das nicht mal parallelisieren müssen um es effizient zu bekommen. Auch habe ich Sorgen bei deinen C++ Skills, wenn du versuchts Sachen zu parallelisieren. Ich glaube das wird nicht gut gehen und mit sehr viel undefined behavior enden.

Baal Netbeck schrieb:
Was das ist, habe ich gegoogled.....aber bei einem neuen Projekt eingefügt, sagt er mir halt, dass er die Datei nicht finden kann.........was ich komisch fand, da sie von dem ursprünglichen Programm genutzt wurde und jetzt soll sie plötzlich weg sein
Visual Studio hat das default-behavior für Precompiled-Header geändert. Du hast vermutlich mit Visual Studio 2017 das alte Projekt erstellt und dort einen Precompiled-Header bekommen, und das neue Projekt mit Visual Studio 2019, wo du standardmäßig keinen mehr bekommst.

Gruß
BlackMark
 
  • Gefällt mir
Reaktionen: Baal Netbeck
Alle Achtung. Hartnäckig bist du ja.
Der Rat war sehr gut: Erfinde nicht immer das Rad neu.
 
BlackMark schrieb:
Wenn du es schon von Hand parsen willst, dann nimm doch bitte regex, die sind mittlerweile in der C++ standard library und nehmen dir sehr viel Arbeit ab.
Werde ich mir wohl mal angucken.
BlackMark schrieb:
Also bei guter Dokumentation sollte es dich bei weitem nicht so viel Zeit kosten wie es von Hand zu machen.
Ist leider so....Man könnte sagen mir fehlen da die Erfahrungen, wie man sowas überhaupt angeht....der Crashkurs den ich hatte hat sich mit den ansoluten Basics beschäftigt...int char string und doubble, cout und cin....Ab da habe ich mir den Rest selbst angeeignet.......wenn ich eine Idee habe, wie ich etwas umsetze, ist es für mich daher nicht viel Arbeit das einfach hinzuschreiben......aber neue Befehle sind immer ein großes Problem.....wobei es mir auch Spaß macht das zu entdecken....nur bin ich natürlich frustriert, wenn ich 3h später immer noch rumprobiere.
BlackMark schrieb:
Wenn du natürlich etwas lernen willst, dann musst du es von Hand machen.
Ich muss kein Programmierprofi werden....sonst hätte ich Informatik studiert....aber ich habe die letzten Tage schon einiges Neues gelernt und das war duchaus befriedigend.
BlackMark schrieb:
Ja, natürlich. Wobei das Lesen der Datei nicht dein Bottleneck sein sollte, sondern deine Auswertung, die sehr ineffizient ist.
Also das finden und auch mein händisches sortieren ist im grunde sofort erledigt wenn ich den Pfad eingegeben habe......ich habe da ja auch höchstens ein paar dutzend Dateien drin.

Was sehr lange dauert ist das einlesen....ich weiß nicht ob es das einlesen an sich ist, oder mein überführen in Strings oder die IF abfragen.....oder mein Variablenmanagement.....aber ich habe in der funktion massiv Zeit gespart, indem ich bei dem "testweisen einlesen", das nur guckt ob es eine Fraps/Ocat /CapframeX Datei ist, und ob sie eine passende größe hat, nur die erste Zeile zerlege......die anderen Zeilen eben als ganzes einlese, aber dann ignoriere.
Bei dem zweiten einlesen, dass dann den eigentlichen Inhalt einliest, kann ich das logischerweise nicht überspringen......naja ist kein Beinbruch......und die Fraps Dateien brauchen auch nicht so lange, weil die in jeder Zeile nur zwei Spalten haben und nicht 16 oder 17 wie die anderen.
BlackMark schrieb:
Auch habe ich Sorgen bei deinen C++ Skills, wenn du versuchts Sachen zu parallelisieren. Ich glaube das wird nicht gut gehen und mit sehr viel undefined behavior enden.
Ich traue mir zu, darauf zu achten, dass während der code parallel läuft, ich keine Variablen verändere, die von mehreren benutzt werden........... ich traue mir noch nicht zu, die Befehle dazu korrekt zu verwenden. ;)
BlackMark schrieb:
Visual Studio hat das default-behavior für Precompiled-Header geändert. Du hast vermutlich mit Visual Studio 2017 das alte Projekt erstellt und dort einen Precompiled-Header bekommen, und das neue Projekt mit Visual Studio 2019, wo du standardmäßig keinen mehr bekommst.
Das wird es sein....dann brauche ich mri da keine Gedanken drum zu machen. :)
LencoX2 schrieb:
Alle Achtung. Hartnäckig bist du ja.

Ist das an mich gerichtet?

Ich bin mir nicht sicher, ob das ein Kompliment ist oder nicht:D
 
Baal Netbeck schrieb:
Was sehr lange dauert ist das einlesen....ich weiß nicht ob es das einlesen an sich ist, oder mein überführen in Strings oder die IF abfragen.....oder mein Variablenmanagement.
Ich habe mich nicht klar genug ausgedrückt, es ist nicht direkt das Einlesen, also es ist nicht die Lesegeschwindigkeit deiner Platte, sondern wie du einliest:
C++:
while (getline(csvread, s)) {
    string inhalt = s;
    inhalt.erase(remove(inhalt.begin(), inhalt.end(), ' '), inhalt.end());
    istringstream stm(inhalt);
    string str;
    stm >> ws >> str;
    zeileneintraege = split3(str, ',');
    // [...]
}
Zeilenweise lesen ist langsam. vector::erase ist langsam. Stringstreams sind langsam. Dein split3 hat wieder zeilenweises Lesen und Stringstreams, und auch noch vector::push_back, das ist ebenfalls langsam.
Du verwendest sehr viele Sachen die prinzipiell langsam sind, nicht alle davon wirst du komplett beseitigen können, aber einiges schon.
Wenn du das Ganze schnell machen willst, dann musst du die ganze Datei auf einmal in den RAM laden, das bringt sicherlich schon sehr viel. Wenn du dann immer noch Probleme hast, musst du das Parsen vereinfachen. Eigentlich musst du nur ein mal über die Datei iterieren, die Whitespaces kannst du ignorieren, alles andere rausspeichern und bei , und newline trennen.

Oder du verwendest einen csv-Parser, der genau das schon schnell für dich implementiert. Zum Beispiel den hier: fast-cpp-csv-parser

Baal Netbeck schrieb:
Ich traue mir zu, darauf zu achten, dass während der code parallel läuft, ich keine Variablen verändere, die von mehreren benutzt werden........... ich traue mir noch nicht zu, die Befehle dazu korrekt zu verwenden.
Also das Threading Interface von modernem C++ ist unglaublich einfach zu verwenden. std::thread myThread(threadFunction); und deine Funktion threadFunction läuft als Thread. Kannst dich ja mal damit spielen und dann herzeigen.

Gruß
BlackMark
 
  • Gefällt mir
Reaktionen: Baal Netbeck
Zurück
Oben