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

Baal Netbeck

Fleet Admiral
Registriert
Apr. 2008
Beiträge
11.936
Hi, ich denke der Titel sagt schon grob, woran ich gerade scheitere. ;)

Ich bin ein ziemlicher Programmier Noob....ich habe keine echte Informatikvorlesung besucht, sondern nur einen Crashkurs für C++.
Ich kann .csv Dateiein mit speziell formatierten Daten einlesen....die Daten verarbeiten und sie wieder in csv/txt Dateien abspeichern.
Ich arbeite fast ausschließlich mit arrays und globalen Variablen...und gigantischen Monstern aus while Schleifen und if/else Verkettungen.

Bis jetzt bin ich damit zurechtgekommen und ich habe ein sehr längliches Programm zum Auswerten von Frametimemessungen.
Ich bin froh, dass das alles so funktioniert, und auch wenn ich daran arbeite den Quellcode zu entschlacken(vieles unnötig und umständlich weil es durch ausprobieren "gewachsen" ist), so möchte ich bei C++ und Visual Studio 2017 bleiben weil ich die Arbeit nicht nochmal machen möchte.

Situation :
Allerdings möchte ich bald eine weitere Benchmarkreihe machen und dafür sehr viele Messungen verarbeiten....mit meiner jetzigen Methode ist das langwierig und ich muss mich super konzentrieren um keine Fehler zu machen.
Mein Programm liest bis zu 10 Datensätze ein, allerdings aus festgelegten Dateien im Programmordner....und schreibt die Ergebnisse in fest benannte Dateien.

Ich habe also z.B. 10 Messungen mit Fraps oder OCAT/CapFramX gemacht und die in den passenden Ordner "C:\Users\Bhaal\Desktop\2700x bench\RotTR 1440 custom 4,2 4+4on 4x8 2800 cl14haupt auto subtimings RVII UVOC" geschoben.....dann würde ich jetzt die Dateien im Ordner nach dem Alter ordnen.....die älteste Datei öffnen, STRG+ a und c drücken....schließen und im Programmordner die Dateien Framtime1.csv öffnen und STRG+ a und v und s drücken...schließen und das für alle Dateien wiederholen, bis alles Inhalte rüberkopiert sind...das C++ programm ausführen und mit einer "4" auswählen, dass ich nicht eine, 3 oder 5 Dateien auswerten möchte sondern alle 10....dann erhalte ich mehrere Dateien mit Ergebnissen, die ich dann in den Ordner mit den Originaldaten verschiebe und ich mich an den nächten Ordner machen kann.:pcangry:
Auch später die Daten in OriginPro einzufügen um sie darzustellen ist nervig, da die Ergebnisdateien alle die gleichen Bezeichnungen haben und ich sie nach dem Ascii einlesen erst noch passend umbenennen muss....hätten die Ergebnissdateien bereits einen passenden namer wie der Ordner, wäre das alles viel einfacher.

Jetzt möchte ich auch noch die Möglichkeit haben bis zu 16 Dateien einzulesen.......und vor allem möchte ich das manuelle kopieren ersetzen und auch die Beschriftung automatisieren.....automatisch auswählen, wie viele Dateien bentuzt werden usw. :love:
...................
Mein Plan ist jetzt, dass ich die Frametimemessungen weiterhin in Ordner verschiebe und ich noch mehr darauf achte, dass die Ordner auch eine eindeutige Bezeichnung haben.......dann gehe ich in den Ordner und kopiere mir die Adresse aus der Adresszeile.....starte mein Programm und es bittet mich den Pfad einzugeben........und dann soll das Programm den Ordner nach files durchsuchen.....nur die .csv files merken, zählen und dann dem Alter nach sortieren....und die Dateinamen in ein Array mit 16 Einträgen einsortieren....sind es mehr Dateien, werden Überzählige ignoriert, aber ich möchte wissen, ob es zu viele sind, so dass ich einen Hinweis im Programm ausgeben kann der darauf hinweist.

Ich habe mir inzwischen angeeignet, wie ich den Pfad einlese und nach \ zerlege....so komme ich an den Namen des Ordners, den ich für die spätere Benennung der Ergebnisfiles brauche und ich habe den Pfad um die Dateien im Ordner anzusprechen und direkt einzulesen.....Ergebnisse direkt in diesen Ordner zu speichern usw.

Aber ich finde keinen Anfang dazu, wie ich an die Files im Ordner komme....Ich habe einiges gefunden, dass "FindFirstFile" und "FindNextFile" nutzt, aber ich verstehe die Synthax nicht und es arbeitet mit Sachen wie "FILE_ATTRIBUTE_DIRECTORY" und irgendwie fehlt mir da das Wissen um den Diskussionen zu folgen.....auch bin ich gar nicht vertraut mit pointern....

Ich habe hier auch etwas gefunden, dass eventuell nützlich sein könnte:
http://www.cplusplus.com/reference/stl/
aber auch da fehlt mir der Ansatz um anfangen zu können. :(

Mein Plan war es, mit irgendeiner Funktion die files im eingegebenen Dateipfad einzulesen und eventuell in so einen container zu speichern....mit name und timestamp.

Dann würde ich den container sortieren(ich hoffe das funktioniert so einfach und ich muss nicht irgendwie mit Datum und Urzeit hantieren) und dann den sortierten container nach .csv dateien durchsuchen .......ich dachte ich könnte die Dateinamen nach "." trennen und als letzten Eintrag sollte ich ja dann "csv"(oder was anderes) finden....und nur wenn da "csv" steht, wird der Dateiname in ein array[16] gespeichert...dabei die Anzahl gezählt....und wenn das array voll ist, dann suche und zähle ich zwar weiter, bis ich alle Einträge des containers durch habe, aber ich höre auf, die in das array zu speichern............ab da sollte ich selbst zurecht kommen. :)

Könnt ihr mir mit einfachen Worten helfen zu verstehen, wie ich das anstelle?:heilig:
 
Ich denke fuer so etwas ist C++ nicht die richtige Sprache. Gerade da du noch nicht so viel programmiererfahrung hast, waere das lernen einer, fuer diesen Zweck, passenderen Sprache nicht verkehrt. In z.B. Python oder JS solltest du das ganze einfacher und unkomplizierter hinbekommen.
 
.......ja...mag sein, dass das außerhalb von C++ einfacher zu programmieren ist, aber ich habe unzählige Zeilen code für die Fehlerrechnung und verschiedenste Statistik-Parameter, die ich jetzt alle in C++ habe....die möchte ich nicht in eine neue Sprache übersetzen.....da müsste ich mich wieder mit neuen Eigenarten vertraut machen und für alles neu manuell verifizieren, dass die Berechnungen machen was ich geplant habe.

diese <filesystem> library sieht sehr interessant aus. :)

.........leider stellt mich die Anwendung so eines Haufens an Befehlen weiterhin vor große Anfangsschwierigkeiten. ;)
 
Zuletzt bearbeitet:
Baal Netbeck schrieb:
Aber ich finde keinen Anfang dazu, wie ich an die Files im Ordner komme....Ich habe einiges gefunden, dass "FindFirstFile" und "FindNextFile" nutzt, aber ich verstehe die Synthax nicht und es arbeitet mit Sachen wie "FILE_ATTRIBUTE_DIRECTORY" und irgendwie fehlt mir da das Wissen um den Diskussionen zu folgen.....auch bin ich gar nicht vertraut mit pointern....
https://www.bfilipek.com/2017/08/cpp17-details-filesystem.html
https://stackoverflow.com/questions...the-list-of-files-in-a-directory-using-c-or-c
 
  • Gefällt mir
Reaktionen: Baal Netbeck
Da du Visual Studio verwendest gehe ich davon aus, dass als Zielplatform Windows benutzt wird?

Dann gebe ich dir folgende MS-Hilfeseite mit komplettem Beispiel an die Hand: https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory

Unterhalb des Kommentars "List all files in the directory with some info about them" wird in einer Schleife das angegebene Verzeichnis durchlaufen. In den dortigen Else-Zweig läuft das Programm nur wenn es KEIN Verzeichnis ist, sondern eine Datei. Das "ffd"- Objekt vom Typ WIN32_FIND_DATA enthält unter anderem auch das "Erstelldatum" der Datei in "ftCreationTime".

Ich hoffe das hilft dir etwas weiter, um zumindest mal die Dateinamen zu ermitteln.
 
  • Gefällt mir
Reaktionen: Baal Netbeck
Wenn ich anfange
Code:
using namespace std::filesystem
zu nutzen......ersetzt das dann
Code:
using namespace std;
???
Kann ich zwischen denen wechseln, also nur für die Funktion die mit den Dateien hantiert aus das andere namespace wechseln und am Ende wieder zurück?
 
Balkoth schrieb:
Da du Visual Studio verwendest gehe ich davon aus, dass als Zielplatform Windows benutzt wird?

Dann gebe ich dir folgende MS-Hilfeseite mit komplettem Beispiel an die Hand: https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
Lieber nicht.

Wenn man speziell Windowsn ansprechen möchte, dann verwendet man heute wohl C++/WinRT. Keiner muss sich den C-Schmerz antun.

Aber wozu speziell die WinAPI nutzen, wenn man filesystem in der STL hat?

Baal Netbeck schrieb:
Wenn ich anfange
Code:
using namespace std::filesystem
zu nutzen......ersetzt das dann
Code:
using namespace std;
???
Nein:
using std: du brauchst keinen std Prefix mehr verwenden
using std::filesystem: du brauchst keinen (std)filesystem Prefix mehr für Elemente aus std::filesystem mehr verwenden.

-> Ergänzt sich.
 
Warum? Ganz einfach: Er ist Anfänger, hat keinen Plan (no offense, ich finds mutig was du vorhast, auch die Bereitschaft hierfür) und ich habe ihm ein komplettes Sample zur Ermittlung der Dateinamen gegeben. Du hast Ihm Links ohne Erklärung gegeben.
 
new Account() schrieb:
using std::filesystem:
Das funktioniert bei mir leider nicht...filesystem wird rot unterschlängelt mit dem Hinweis : namespace std hat keinen Member "filesystem

ich konnte einige der Befehle eingeben wenn ich #include<filesystem> benutzt habe...aber nur einen Teil und irgendwie habe ich auch keine funktionierende funktion hinbekommen.

Die Beispielfunktion aus https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
wirft zwar fehler bezüglich der Fehlerausgabe, aber die könnte ich umschreiben....es muss für mich kein Textfenster werden...ich bin auch mit einem cout zufrieden der sagt..."nope!"
 
  • Gefällt mir
Reaktionen: Balkoth
Baal Netbeck schrieb:
Das funktioniert bei mir leider nicht...filesystem wird rot unterschlängelt mit dem Hinweis : namespace std hat keinen Member "filesystem
Dann googled man und findet die Lösung des Problems:
https://stackoverflow.com/questions/50668814/vs2017-e0135-namespace-std-has-no-member-filesystem
Balkoth schrieb:
Warum? Ganz einfach: Er ist Anfänger, hat keinen Plan
Dann macht es natürlich Sinn ewig komplexe und seitenlange C-Konstrukte der WinAPI in C++ zu verwenden, wenn man zum Dateien auflisten stattdessen einfach nur folgendes nutzen kann (nahzu 1:1 kopiert aus Link):
C++:
#include <string>
#include <iostream>
#include <filesystem>

int main()
{
    std::string path = "/path/to/directory";
    for (const auto & entry : std::filesystem::directory_iterator(path))
        std::cout << entry.path() << std::endl;
}

Balkoth schrieb:
Du hast Ihm Links ohne Erklärung gegeben.
Links, welche sich selbst erklären - wenn man den Inhalt denn liest.
 
Balkoth schrieb:
und ich habe ihm ein komplettes Sample zur Ermittlung der Dateinamen gegeben.
Und das ist auch soweit super, weil ich es einfügen kann und es kompilliert.....nur scheiter ich an der syntax....da wird eine int tmain() angelegt....ist das irgendwie in konkurrenz zu meiner int main()??

Auf jeden fall hat die als Argumente (int argc , TCHAR *argv[]) ....ich finde auf der Seite keine Erklärung, was ich da eingeben muss um die aufzurufen....ich hätte meinen Pfad komplett als String...oder die Verzeichnisse als Vektor mit strings.
Jetzt will die funktion aber int und TCHAR(ist einfach ein char oder?)....

new Account() schrieb:
Links, welche sich selbst erklären - wenn man den Inhalt denn liest.
Naja um das lesen zu können braucht man schon etwas erfahrung...Ich lese da nur einen haufen Klassen und Befehle ohne zu wisen wie man die anwenden kann... dein kurzes code Beispiel sieht einfach aus, aber das std filesystem will er trotzdem nicht nehmen....ich bin auf die neueste sprache gegangen...habe experimentell aktiviert...kein Unterschied.
 
Baal Netbeck schrieb:
..ich bin auf die neueste sprache gegangen...habe experimentell aktiviert...kein Unterschied.
Welche Version von Visual Studio?
Hast die anderen Tipps aus den Kommentaren auch probiert?

Welche Optionen hast du zur Auswahl (neben neue Version)?
Alle Updates installiert (von VS 2017)?
 
@ne Account() und @Balkoth
Im Moment probiere ich an beiden Lösungen herum. ;)

Das mir using namespace std habe ich erstmal auf Eis gelegt....ich kann ja auch die Befehle wie in seinem Beispielcode wie
Code:
std::filesystem::directory_iterator(path)
nutzen.....werden ja überschaubar viele bleiben....so spuckt es mir zumindest schonmal die Dateinamen als
cout aus. :)

So könnte ich die in einen Vektor speichern........das wäre schonmal etwas......aber ich bin auch der anderen Lösung nicht abgeneigt....und vor allem müsste ich noch an die zeiten kommen...
 
new Account() schrieb:
Mit dem Kram hantiere ich jetzt schon eine Weile rum....ich glaube
Code:
auto ftime = std::filesystem::last_write_time(entry);
In deine Schleife von oben eingefügt, liest die Zeiten aus.....und ich nehme an als "vergangene Sekunden nach 1970".......aber ich kann das nicht in einen mir bekannten Typ konvertieren.....will ich es abspeichern oder ausgeben muss ich es ja in int oder double konvertieren, aber das scheint niemand zu machen....alles was ich bis jetzt so finde, konvertiert es in Datumsangaben+Uhrzeit.....was für mich ja nur hinderlich ist.
 
Baal Netbeck schrieb:
aber ich kann das nicht in einen mir bekannten Typ konvertieren.....will ich es abspeichern oder ausgeben muss ich es ja in int oder double konvertieren, aber das scheint niemand zu machen...
In dem Link, den ich gepostet habe, ist doch ein Beispiel für die Ausgabe gewesen.
Hier auch nochmal ein Beispiel: https://en.cppreference.com/w/cpp/chrono/time_point

Wenn du die Zeit zwischen Uhrzeitstart und dem Zeitpunkt haben möchtest, kannst du außerdem time_since_epoch nutzen (was dort auch aufgelistet ist).
Das liefert eine duration zurück: https://en.cppreference.com/w/cpp/chrono/time_point/time_since_epoch

Mit Funktionen von hier: https://en.cppreference.com/w/cpp/chrono/duration
kannst du das dann in z.B. Sekunden oder Stunden umrechnen.
 
new Account() schrieb:
In dem Link, den ich gepostet habe, ist doch ein Beispiel für die Ausgabe gewesen.
Ja...als Datum......ich wollte es aber als Zahl haben......also vermutlich muss ich dann über duration bzw time since epoch gehen, aber das ist noch ziemlich unwillig......man muss halt jedes mal irgendwelche Templates erstellen(glaube ich zumindest) und irgendwelche classen definieren, was bei mir irgendwie selten funktioniert, weil ich es auch einfach planlos ins Programm kopiere. ;)

Ich wollte sie als Vektor speichern, aber ich kann keinen vektor
Code:
vector <std::filesystem::file_time_type> ftimev;
erstellen(Edit...aus irgendeinem Grund geht es inzwischen)....ich konnte aber arrays erstellen.....da ich nicht mega viele Dateien in einem Ordner haben werde, komme ich da sicherlich mit [50] oder so hin.
 
Zuletzt bearbeitet:
Zurück
Oben