Textdateien zeilenweise einlesen

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

theo hat geschrieben:irgendwann muss man die sowieso ins File schreiben, also warum nicht gleich dann wenn's passiert?
Wenn man 100-mal hintereinander schreibt (z.B.

Code: Alles auswählen

for i := 1 to 100 do begin
  klasse.strings[i] := inttostr(i);
end;
klasse.free;
Und die Datei ist 100 000 Zeilen lang dann dauert das direkte schreiben (was jedes Mal knapp 100 000 Zeilen auf der Platte lesen und schreiben muss) ungefähr 100 mal so lange wie ein gecacheter Zugriff, der erst bei free irgendwas auf die Platte schreibt.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Das lässt sich ja abfangen ... ich halt es trotzdem für sinnvoll es gleich auf die platte zu schreiben z.b. wenn innerhalb der nächsten 100ms nichts mehr kommt wirds geschrieben.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

@mschnell: Ja, obwohl ich mir nicht ganz sicher bin, ob das Betriebssystem da evtl. auch noch was optimiert.
Wie würde denn dein Cache aussehen? Der braucht wahrscheinlich auch wieder Memory, und das wollten wir doch gerade nicht.
Wie schon gesagt, glaube ich, dass in dem meisten Fällen für so einen Zweck ge-addet wird. Das müsste schnell sein.
Für das was du in deinem Beispiel machst, wäre die TFileStringList natürlich nicht optimal. Auch nicht für sortieren und sowas.
Aber für Add und Get könnte man sie schon ordentlich optimieren.

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

dann müsst ihr gleich ein DB nehmen. die TStringlist sollte nur kleine mengen an Daten speichern wobei ich weiß hier auch wieder keine Werte was klein heißt.... könnte mir vorstellen das eine 2MB Große Datei schon Probleme machen könnte.
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Es spricht ja keiner von TStringList, sonder von einer Klasse, die ein ähnliches Interface hat, aber direkt auf Files arbeitet und nicht den ganzen Krempel ins Memory lädt.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

theo hat geschrieben:Wie würde denn dein Cache aussehen?
Ich stelle mir den Cashe als eine TStringlist vor, in der bis zu MaxCachedLines (als Property von TFileStrinList konfigurierbar) Zeilen gehalten werden. Ein Integer DynArray hält dann die Zuordnung "String in CashStringList" -> "Zeile in der Datei". Auf Anforderung (TFieStringList.Flush) oder wenn der Cache zu voll wird, werden alle oder einige der Strings in die Datei geschrieben. Viele auf einmal ist sehr viel effektiver, da ein Austauschen einer Zeile in der Datei wegen der unterschiedlichen Zeilenlängen ja nicht geht. Die Datei muss also völlig umgemodelt werden. Die optimale Methode dazu zu finden ist nicht so einfach. Man muss (wenn z.b. eine Zeile bei 1/3 und eine bei 2/3 einer Riesen-Datei jeweils ein Byte größer als vorher gespeichert werden soll) vermutlich Teile der Hauptdatei auf Hilfsdateien auslagern oder ähnliches.

-Michael

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Wie gesagt, ich glaube nicht so richtig an den Cache.
Das kann ganz schön kompliziert werden.
Wie willst du denn verschiedene Aktionen an verschiedenen Stellen cachen und v.a. nachher in "einem Rutsch" ausführen?
Beispiel:

Code: Alles auswählen

FileStrings[12]:='test';
FileStrings.Delete(15)
FileStrings[10006]:='hallo';
FileStrings.Add('test');
FileStrings[FileStrings.Count-1]:='test test';
Da nützt dir der Cache imho nix, du musst trotzdem x-mal umkopieren.
Dein Beispiel oben lässt sich auch vom Benutzer der Klasse optimieren, ohne dass die Klasse selber cached:

Code: Alles auswählen

for i := 1 to 100 do begin
  tempstringlist.add(inttostr(i));
end; 
FileStrings[1]:=tempstringlist.text; //in "einem Rutsch" eingefügt.
Hilfsdateien gefallen mir auch nicht. Das geht auch mit einer Datei.
Blockweise umkopieren. Eine Methode für Wachsen, eine für Schrumpfen.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Is ja auch alles quatsch Dateizugriffe cacht das Betriebssystem und da sollte man das auch belassen.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

pluto
Lazarusforum e. V.
Beiträge: 7192
Registriert: So 19. Nov 2006, 12:06
OS, Lazarus, FPC: Linux Mint 19.3
CPU-Target: AMD
Wohnort: Oldenburg(Oldenburg)

Beitrag von pluto »

Naja, wenn FileStrings ein array währe, währe es kein Problem.

Kann man eigentlich eine Doppelt Verkette Liste irgendiw sinvoll mit einem Array verbinden ? also sprich die Speicher Stelle berechnen ?
(ich glaube erher nicht).

Was du machen könntest währe z.b. einfach häufe suchanfragen zu speichern z.b. 10 Stück. Dann schaust du in dieser Liste zu erst nach ob es den Eintrag schon gibt.... Wie machen das eigentlich DB'S?
MFG
Michael Springwald

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

pluto hat geschrieben:Naja, wenn FileStrings ein array währe,
... dann wäre es eine TStringList

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben:Is ja auch alles quatsch Dateizugriffe cacht das Betriebssystem und da sollte man das auch belassen.
Denk doch bitte 'mal nach !

Um eine Zeile von 10 Byte auf 11 Byte zu ändern muss fast die ganze 1 Gigabyte große Datei kopiert werden, weil ja in Textdateien keine Lücken erlaubt sind.

Um 1000 Zeile zu ändern, die vorher in einer Stringlist gecached worden sind braucht die ganze Datei auch nur einmal kopiert werden. Da hilft der Betriebssystem-Cache ach nicht viel. Wohl aber eine (aufwändige) Verwaltung der geänderten Zeilen.

-Michael
Zuletzt geändert von mschnell am Fr 12. Okt 2007, 13:37, insgesamt 1-mal geändert.

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Na toll um diesen fall zu vermeiden kannst eh nur die ganze Datei im Speicher halten ergo TStringList nehmen, wer denkt denn hier nicht nach ? Und wo hast du schon mal Gigabytegrosse Textdateien gesehn ? Ich denk das ist Humbug.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
theo
Beiträge: 10927
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Das sehe ich auch wie Christian. Die Klasse sollte nur einen fixen Buffer verwenden, um etwas schneller lesen und schreiben zu können.
Aber eine beliebig anwachsende Stringlist macht das Ganze zwecklos.

mschnell
Beiträge: 3444
Registriert: Mo 11. Sep 2006, 10:24
OS, Lazarus, FPC: svn (Window32, Linux x64, Linux ARM (QNAP) (cross+nativ)
CPU-Target: X32 / X64 / ARMv5
Wohnort: Krefeld

Beitrag von mschnell »

Christian hat geschrieben:Na toll um diesen fall zu vermeiden kannst eh nur die ganze Datei im Speicher halten ergo TStringList nehmen, wer denkt denn hier nicht nach ?
Sinn macht TFileStringList sowieso nur bei Riesen-Dateien. Und da ist es absolut sinnvoll, die Änderungen im RAM zu halten und gesammelt in die Datei zu schreiben.

Mit viel RAM wird's natürlich besser. Dann nimmt man aber besser eine TStringList.
Christian hat geschrieben:Und wo hast du schon mal Gigabytegrosse Textdateien gesehn ? Ich denk das ist Humbug.
Wie schon öfters gesagt, für nicht allzu große Textdateien macht das ganze keinen Sinn, da nimmt man natürlich TStringList. Das ist natürlich auch der Grund, warum es noch keiner programmiert hat.

-Michael

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Also bei 5-50 mb Datein macht das schon sinn.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Antworten