C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige
-
@jasmin89 sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@wob: Gibt fgets auch die gelesene Länge zurück?
Ach mist, tut es nicht.
Oder meinst du strln zu verwenden und mit einer int Variable diese dann immer zu addieren
Also: z.b long int length = strlen(puffer)+length;Ich wollte den von mir erträumten Längen-Rückgabewert addieren. Sorry!
Die 77273022464 sind die Dateigröße.
Die solltest du einmalig am Anfang automatisch ermitteln (siehe https://www.c-plusplus.net/forum/post/2617554)
Ich verwende die Vergleichsfunktion SGA_stricmp da ich nicht alles in Großbuchstaben eingeben möchte.
schon klar, aber warum
tolower
UNDtoupper
nacheinander? Wie unterscheidet sich das davon, wenn du alles nur in Kleinbuchstaben umwandeln würdest, ohne es vorher in Großbuchstaben gewandelt zu haben? Wenn du AbC suchst und daraus erst ABC machst, um dann abc daraus zu machen, wozu ist dann der Zwischenschritt mittoupper
gut?
-
@DocShoe sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Das Ganze birgt eine Gefahr: Der Puffer muss nicht nullterminiert sein, weil sein Inhalt vom Dateiinhalt abhängt und dein fgets Aufruf den ganzen Puffer beschreibt, inklusive des letzten Zeichens. Zur Sicherheit solltest du den Puffer um ein Byte vergrößern und das mit 0 besetzen, damit ist immer sichergestellt, dass der Puffer nullterminiert ist
Siehe https://en.cppreference.com/w/c/io/fgets:
Reads at most count - 1 characters from the given file stream [...] If bytes are read and no errors occur, writes a null character at the position immediately after the last character written to str.
Das ist also sichergestellt, ohne dass du selbst mit -1 rumhantieren müsstest oder den Puffer vergrößern müsstest.
-
@DocShoe sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@Th69
Weiss nicht... hängt davon ab, wie lange der Vorgang dauert, wenn ich auf einen prozentualen Fortschritt schaue und da passiert längere Zeit nix, dann vermute ich, dass da iwas hängt. Prozentangaben mit Nachkommastellen finde ich da durchaus ok. Mann kann natürlich auch noch die Dauer anzeigen, die seit Start verstrichen ist, dann wäre ich auch mit ganzzahligen Prozentangaben glücklich.Du hast mich da mißverstanden. Bei einer Anzeige mit 2 Nachkommastellen würde man eben in Deziprozentwerten rechnen (so wie man Geldwerte auch in Cent oder sogar noch kleinere Werte - z.B. für Bankensysteme - berechnet).
-
@wob sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Siehe https://en.cppreference.com/w/c/io/fgets:
Reads at most count - 1 characters from the given file stream [...] If bytes are read and no errors occur, writes a null character at the position immediately after the last character written to str.
Das ist also sichergestellt, ohne dass du selbst mit -1 rumhantieren müsstest oder den Puffer vergrößern müsstest.
Sieh man einer an, man lernt nicht aus
-
@Th69 sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Du hast mich da mißverstanden. Bei einer Anzeige mit 2 Nachkommastellen würde man eben in Deziprozentwerten rechnen (so wie man Geldwerte auch in Cent oder sogar noch kleinere Werte - z.B. für Bankensysteme - berechnet).
Aber warum "würde man [...] in Deziprozentwerten rechnen", was soll da der Vorteil sein? Verstehe ich nicht. Ich sehe da kein Problem mit einer float-Division. Du willst dem Anwender ja trotzdem 17,54% anzeigen und nicht 1754. Du müsstst dich also auch noch selbst darum kümmern, da ein Dezimaltrenner einzublenden. (das ist ja gerade nicht wie bei Geld, wo es fixe Minimaleinheiten wie eben z.B. Cent gibt).
-
Es ging ja darum, die Prozentzahl nur dann anzuzeigen, wenn sie sich geändert hat (und nicht bei jedem Schleifendurchlauf):
if (pct != current_pct) { current_pct = pct; // output }
Und bei Fließkommazahlen wäre dieser Vergleich bei jedem Schleifendurchlauf immer positiv.
Aber wo ich jetzt genauer darüber nachdenke, müßtefabs(pct - current_pct) >= 0.01
(bei 2 Nachkommastellen) als Bedingung genügen.Würde mich trotzdem interessieren, ob die Umwandlung in Fließkommazahlen und deren Ausgabe nicht langsamer ist (bei so großen GB-Dateien), als die Verwendung einer optimierten Fixkommazahl-Ausgabe.
-
@jasmin89 sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@DirkB: Wieso hat denn float Nachteile gegenüber double, bezüglich Konvertierung. Verstehe nicht genau was du mit konvertierung meinst. Wenn ich nur float verwende, wird da was konvertiert?
Gerechnet wird bei Fließkommaoperationen in double.
printf
nimmt bei Fließkommatypen auch mindestens doubleAlso Berechnung in double, Konvertierung nach float und wieder nach double für printf.
float hat nur bei sehr großen Arrays Vorteile gegenüber double.
-
Damit hier kein falscher Eindruck bei @jasmin89 aufkommt: Diese Rechentricks sparen höchstens ein oder zwei CPU-Takte, wenn überhaupt so viel. Takte, die völlig irrelevant sind, weil dein Programm die meiste Zeit entweder auf die Daten aus der Datei wartet, oder (bevor du dein Problem behoben hattest) darauf, dass deine Prozentausgabe auf der Konsole landet. Beides Operation, die um Größenordnungen länger dauern als ein paar float/double Berechnungen auf Teilen der CPU, die wahrscheinlich sowieso nichts besseres zu tun haben.
-
@Th69 sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
if (pct != current_pct)
Du kannst ja auch schreiben
if (pct >= current_pct + 0.01)
- außerdem hat man vielleicht noch eine "ETA hat sich um mindestens 10 Sekunden geändert"-Bedingung.Wenn du nutzlose Mikro-Optimierungen willst, kannst du auch
next_update_pct = pct + 0.01;
undif (pct >= next_update_pct)...
schreiben.
-
Danke für die Hilfe. Ich konnte einige Tipps umsetzen.
@DocShoe: Danke für den Tipp. Habe den Debugger angeworfen und tatsächlich es werden immer 300 Byte Blöcke eingelesen. Das war mir so nicht bewusst. Dann wäre eine Lösung eine solche Indexdatei zu erstellen, damit ich nur z.b 300 Byte einlesen muss. Habe ich das richtig verstanden? Sonst eine andere Möglichkeit nur 300 Byte von einer Zeile einzulesen habe ich nicht? Ich habe probiert das Array um 1 Byte größer zu machen und das Array mit '\0' zu füllen. Aber es wird immer die gesamte Zeile, jeweils 300 Byte, eingelesen bis \n.
@wob: Du hast recht tolower UND toupper nacheinander macht nicht viel Sinn. Ich habe das ausgebessert.
-
Ist das mit den 300 Zeichen eine Anforderung (d.h. du willst nur die Treffer aus den ersten 300 Zeichen, und es könnte auch Treffer nach 300 geben, die du ausschließen möchtest), oder ist das eine voreilige Optimierung (d.h. du weißt es kommt nur in den ersten 300 Zeichen vor und denkst, das wäre irgendwie effizienter, wenn du das so machst)?
-
Das ist eine voreilige Optimierung, das was ich Suchen möchte kommt nur in den ersten 300 Zeichen vor. Ich dachte halt dass die Suche dann schneller wäre wenn ich nicht die Gesamte Zeile einlesen muss.
-
@jasmin89 sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Das ist eine voreilige Optimierung, das was ich Suchen möchte kommt nur in den ersten 300 Zeichen vor. Ich dachte halt dass die Suche dann schneller wäre wenn ich nicht die Gesamte Zeile einlesen muss.
Dann spar dir das einfach. Du musst schließlich den Rest der Zeile auch einlesen, um das Ende der Zeile zu finden. Dateien sind bloß eine Folge von Zeichen, Zeilen haben keinerlei technische Bedeutung. Zeilen sind bloß eine Interpretation eines bestimmten Zeichens, da steckt aber nicht mehr dahinter, als dass das Zeichen Nummer 65 als 'A' interpretiert wird.
Man kann zwar mutmaßen, ob sich vielleicht Optimierungen dadurch ergeben, dass man sich eventuell ein paar Suchoperationen sparen kann, aber oft ist einfacher auch schneller. Mein Tipp daher, was du ausprobieren solltest: Datei blockweise lesen (gerne auch große Blöcke, die kleinste logische Einheit alter Festplatten ist 4kB, heutzutage bekommt man aber auch leicht 512kB in einem Rutsch) und die Blöcke durchsuchen. Aufpassen an den Rändern, dass man nichts verpasst, wenn der Suchbegriff genau auf einer Kante liegt. Beim Lesen möglichst stumpf und unformatiert lesen, also
fread
.Was willst du am Ende haben? Gegebenenfalls könnte es dadurch schwieriger werden. Die Anzahl der Treffer ist einfach. Den Treffer selbst? Auch trivial. Die Zeilennummer der Treffer? Dann müsste man noch mitzählen, an wie vielen Zeilentrennzeichen man vorbei gekommen ist, auch einfach. Wenn du aber beispielsweise die ganze Zeile zu einem Treffer haben möchtest, wird es leider doch etwas kompliziert, weil dann das blockweise Lesen nicht mehr so einfach ist.
-
Das Blockweise lesen klingt interessant. Aber habe ich da wirklich auch eine schnellere Suche? Denn ich muss ja trotzdem immer den gesamten Block durchsuchen. Wenn nichts gefunden wurde wird der Nachfolgende Block durchsucht. Als Leihe würde ich vermuten dass dies gleichschnell ist als alle Zeilen einzulesen. Ich bin keine Informatikerin, daher kann ich auch falsch liegen.
@SeppJ sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Was willst du am Ende haben?
Am Ende möchte ich einen Eindeutigen Ticker haben mit dem ich einen bestimmten Datensatz zuordnen kann. Ich Suche z.b "great falls". In der 80 GB Datei gibt es mehrere Datensätze die "great falls" beinhalten. Ich als Mensch kann die gefundenen Einträge zu "great falls" richtig interpretieren. Während der Suche merke ich z.b dass "great falls tt" der richtige Datensatz ist. Der Ticker dazu ist z.b. 10584. Ich speichere die gefundene Zeile in der Variable Position, setze den File pointer f auf den Anfang der Datei, springe mit SEEK_CUR zu der gefundenen Zeile und printe die Daten in eine .csv Datei (also die den Ticker 10584 haben). Dann habe ich in der .csv Datei alle Daten mit dem Ticker 10584. Ist etwas kompliziert aber ich habe keine bessere Möglichkeit gefunden. Das ist eben nur ein Teil vom Code.
-
Was genau meinst du mit dem Ticker? Das
position = ftello64(f);
aus deinem Post ganz oben?Wenn das um einen echten, produktiven Einsatzzweck statt den Lerneffekt geht: Ich habe den Eindruck, du programmierst
grep
nach. Du wirst alleine niemals ein Programm schreiben, das besser alsgrep
dein Problem löst.
-
@SeppJ sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Was genau meinst du mit dem Ticker?
Ticker im Sinne von Tickersymbol, d.h. eindeutige ID?
-
@wob sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@SeppJ sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Was genau meinst du mit dem Ticker?
Ticker im Sinne von Tickersymbol, d.h. eindeutige ID?
Ja genau
-
@wob Ich kenne grep nicht und weiß auch nicht was das macht. Ich muss mir das mal anschauen. Ticker: Damit kann ich einen Datensatz zuordnen, dieser ist eindeutig.
Als Beispiel der Datensatz great falls tt hat den Ticker: 10584. Dieser Datensatz enthält 1500 Zeilen. Der Datensatz "great falls rr" mit dem Ticker 19510 interessiert mich nicht und diesen brauche ich nicht. Ich gebe also im Programm "great falls" ein und nach einiger Zeit erhalte ich folgende Ausgabe:great falls rr|Ticker15850 -> Enthält 2501 Zeilen an Daten
great falls ee|Ticker19510 -> Enthält 8500 Zeilen an Daten
great falls tt|Ticker10584 -> Enthält 1500 Zeilen an Daten
great falls uu|Ticker28545 -> Enthält 350 Zeilen an Datenposition = ftello64(f) hier speichere ich die Position des File pointers ab. Wenn ich z.b diese 4 Suchergebnisse habe, weiß ich nun dass ich nur das Ergebnis vom Ticker 10584 benötige. Ich breche dann die Suche ab. Um nun diese Daten zu exportieren, müsste ich den File Pointer wieder an den Anfang der Datei setzen, um genau nach diesen Ticker zu suchen. Damit ich das nicht machen muss, springe ich an diese Gespeicherte position = ftello64(f). Das ist genau die Zeile in der der Ticker 10584 beginnt. Dann kann ich sofort diese Daten exportieren. Das funktioniert auch super.
-
@wob sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
Wer ist "er"? OP heißt @jasmin89, da würde ich per Default "sie" annehmen.
Sorry, hatte nicht auf den Namen geachtet.
-
@DirkB sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@hustbaer sagte in C programm, große .txt Datei durchsuchen, mit Prozent Fortschrittsanzeige:
@DirkB Nachdem er mit
float
rechnet, wird sich der Wert ziemlich oft ändernEins nach dem Anderen.
Vielleicht reichen ja auch 5 Nachkommastellen bei Prozentangaben aus.
Und float bringt auch eher Nachteile gegenüber double, da ja noch Konvertierungen dazwischen erfolgen
Ja, klar. Dazu sind dann aber mehr Änderungen nötig als nur "Ausgabe nur, wenn sich der Wert geändert hat". Man muss erstmal vorher gröber quantisieren, dann vergleichen und dann ggf. ausgeben.