AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Große Textdatei - einzelne Zeile löschen

Offene Frage von "mytbo"
Ein Thema von GummiKuh68 · begonnen am 10. Aug 2022 · letzter Beitrag vom 16. Aug 2022
Antwort Antwort
Seite 1 von 3  1 23      
GummiKuh68

Registriert seit: 10. Aug 2022
Ort: Berlin
4 Beiträge
 
Delphi 7 Enterprise
 
#1

Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 14:36
Moin, moin,

...'...oh Nein, nicht schon wieder Textdatei...' möge manch einer jetzt denken...hatten wir schon!
Ja und habe ich auch alles gelesen - passt aber alles nicht!

Problem:
Ich habe eine Datei die ca. 97 GB groß ist (Klartext: rockyou2021.txt!).
Eins vorneweg - das Problem mit ähnlich großen Dateien habe ich auch während des Supports, wenn ich Messdaten im Rahmen der Fehlersuche analysieren muss.

Nun ist es ja so, dass man Dateien ab einer gewissen Größe nicht mal ebenso in einen Editor laden kann.
Notepad++, PilotEdit, PSPad, usw. machen da irgendwann schlapp! UltraEdit soll das angeblich können, aber da der Download der Demo nicht klappt, kann ich dazu wenig sagen!

Meine Idee war nun, Zeile für Zeile aus der Datei zu lesen und gleich in eine andere Datei zu schreiben, deren Dateiname sich vom Original unterscheidet (Zusatz im Dateinamen: ASCII-Wert des ersten Zeichens!).
Das habe ich auch schon hinbekommen, dass läuft sauber durch.
Das Dumme daran ist, das ich dafür den Rechner die nächste Tage durchlaufen lassen muss - wenn ich das mache, habe ich gleich GAAAAANNZZ andere Probleme!

Aktuell benutze ich folgenden Code:

Delphi-Quellcode:
procedure TForm1.cb3Click(Sender: TObject);
var
  InFile : TextFile;
  i,cnt,s : integer;
  Rest,a: string;
  b :Char;
begin
  assignFile (Infile, 'I:\rockyou2021.txt');
  reset (Infile);
  while not eof (InFile) do
    begin
      readln (InFile, Rest);
      if Rest <> 'then
        begin
          b:=Rest[1];
          of_insstr('I:\rockyou2021-'+inttostr(ord(b))+'.txt',Rest);
        end;
    end;
  CloseFile (InFile);
end;

procedure TForm1.of_insstr(OFile,fstr:string);
var
  OutFile :TextFile;
  i,cnt,s : integer;
  Rest,a,b: string;
begin
  //
  if FileExists(OFile) then
    begin
      assignFile (OutFile, OFile);
      append(OutFile);
    end
  else
    begin
      assignFile (OutFile, OFile);
      rewrite(OutFile);
    end;
  Writeln(OutFile,fstr);
  CloseFile (OutFile);
end;
Ich hab das jetzt auch schon mal laufen lassen und war auch mit dem Ergebnis bisher zufrieden. Allerdings werde ich das wegen der Dauer (habe nach 4 Stunden abgebrochen), immer wieder neu starten müssen.
Das bedeutet aber, das das Programm die Datei von Anfang an ließt und wenn ich die erzeugten Dateien nicht wegschmeiße, alles doppelt reinschreibt, was Mist ist!

Daher war meine Idee, dass ich die Zeile, die ich gerade in eine andere Datei geschrieben habe aus der Ursprungsdatei lösche.
Wenn ich den Code in cb3Click jetzt wie folgt anpasse:

Delphi-Quellcode:
  assignFile (Infile, 'I:\rockyou2022.txt');
  reset (Infile);
  while not eof (InFile) do
    begin
      readln (InFile, Rest);
      if Rest <> 'then
        begin
          b:=Rest[1];
          of_insstr('I:\rockyou2021-'+inttostr(ord(b))+'.txt',Rest);
          writeln(InFile, ''); // '' wäre ok, obwohl noch #13#10 bleibt! Ganz raus wäre noch besser!
        end;
    end;
  CloseFile (InFile);
...bekomme ich zurecht einen Fehler, da die Textdatei mit Reset() nur für das Lesen geöffnet wird.

Was übersehe ich hier?

Ich hatte schon über TStringList nachgedacht aber wenn ich die ca. 97 GB da reinlade...??

TFileStream hatte ich auch schonmal als Idee im Hinterkopf, aber keinen Plan, da ich mit FileStreams bisher eher weniger zu tun hatte.
Zum Testen habe ich mir natürlich eine kleinere Datei gebastelt (s. Anhang).

Vielleicht hat da ja jemand von euch eine Idee!?
Angehängte Dateien
Dateityp: txt rockyou2022.txt (148 Bytes, 13x aufgerufen)
Oliver
Viele Grüße

GummiKuh68
  Mit Zitat antworten Zitat
Rollo62

Registriert seit: 15. Mär 2007
3.908 Beiträge
 
Delphi 12 Athens
 
#2

AW: Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 20:20
Also gefühlt würde ich sagen dass ein zeilenweises Einlesen da nicht ganz optimal ist.
Hast Du mal versucht das Ganze blockweise einzulesen, z.B. 64K Blöcke oder mehr, und die dann im Speicher zu analysieren und blockweise zurückzuschreiben ?
Das ist zwar wesentlich komplexer, aber ich denke das lohnt sich geschwindigkeitsmäßig.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#3

AW: Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 20:53
Zitat:
Was übersehe ich hier?
Daß du zwei Dateien brauchs? (Lesen + Schreiben)

Selbst wenn du vor/nach dem Lesen/Schreiben die Stream-Position "zurück"-setzt,
bekommst du Probleme, wenn die geschriebene Zeile länger ist, als die Gelesene, weil du damit ja bereits die nächste Zeile überschreibst, welche du noch garnicht gelesen hast.

Mit passenden Sharing-Rechten, kann man die gleiche Datei auch mehrmals öffnen, also Lesen und nochmal zum Schreiben.
Aber kann man auch mit nur einem File-Handle und zwei Cursor-Positionen.


Wobei es hier ginge, da Schreiben kürzer ist, als Lesen. (Zeile>'' lesen und Zeile='' schreiben)
Aber nein, SO kannst du keine Zeile löschen, denn die nachfolgenden Zeilen bleiben dennoch an der selben Stelle, was DU selbst verschieben müsstest.
Würdes du die Zeile mit einem '' löschen überschreiben, bliebe der Rest der alten Zeile dennoch erhalten (man könnte diese Zeile höchstsen in der selben Länge z.B. mit mehreren #0 oder ' ' überscheiben, ohne Nachfolgendes verschieben zu müssen)
Code:
** = Zeilenumbruch
_  = Leerzeichen, #0 oder sonstwas

Zeile1**Zeile2**Zeile3**Zeile4** ~ Original

NeueZeile1**e2**Zeile3**Zeile4** ~ Zeile1** durch NeueZeile1** überschrieben (Zeile2** nicht mehr lesbar)
xx**e1**Zeile2**Zeile3**Zeile4** ~ Zeile1** durch xx** überschrieben
**ile1**Zeile2**Zeile3**Zeile4** ~ Zeile1** durch ** überschrieben, aka WriteLn('')

______**Zeile2**Zeile3**Zeile4** ~ Zeile1** durch ______** überschrieben
________Zeile2**Zeile3**Zeile4** ~ Zeile1** durch ________ überschrieben
********Zeile2**Zeile3**Zeile4** ~ Zeile1** durch ******** überschrieben, also 4 Mal WriteLn(''), aber bei ungerader Länge hast'e ein kleines Problem
Zeile2**Zeile3**Zeile4**         ~ Zeile1** gelöscht und Nachfolgendes verschoben (schnell wird es so aber nicht ... weil ja massenhaft Speicher mehrmals verschoben wird)


WriteLn ohne #13#10 heißt Write




TStringList oder TStringStream
und notfalls als 64 Bit kompilieren (ja, neuere Delphis haben ein paar Vorteile)

Auch wenn eine 100M Datei vermutlich ebenfalls in 32 Bit funktioniert.
Man darf aber bedenken, dass der Speicherverbauch beim Laden/Speichern auch mal vorübergehend das 5-fache belegen kann, aber 500M passen ja noch. (5 bei Unicode, aber 2- bis 3-faches auch schon im D7 mit ANSI)




* "nutzlos" zu speichern/überschreiben macht es langsamer
* die alten "Pascal"-Textdatei-Funktionen arbeiten mit einem sehr unoptimalen Buffering = langsam
* TStringList ist nicht ganz optimal und braucht mehr Arbeitsspeicher, aber dennoch ist es viel schneller

* of_insstr sucht und öffnet/speichert immer wieder Dateien = langsam
* * die Dateien (FileHandles) sich zu merken und erst am Ende zu schließen wäre schneller (sind ja nur etwa 60 bis 255 Dateien)
* * oder die QuellDatei mehrmals durchlaufen und jeweils nur EINE "of_insstr"-Datei du behandeln ... zwar mehrmals Lesen aber immer nur jeweils eine Ausgabedatei in einem Rutsch
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (10. Aug 2022 um 21:31 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.007 Beiträge
 
Delphi 12 Athens
 
#4

AW: Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 20:57
Check doch erstmal, ob das Lesen der Datei der Bottleneck ist oder das Schreiben der Einzeldateien.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
Der schöne Günther

Registriert seit: 6. Mär 2013
6.110 Beiträge
 
Delphi 10 Seattle Enterprise
 
#5

AW: Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 21:03
Ist es schon zu spät für mich, oder machst du bei jeder einzelnen Zeile deine Zieldatei auf und wieder zu?
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.345 Beiträge
 
Delphi 11 Alexandria
 
#6

AW: Große Textdatei - einzelne Zeile löschen

  Alt 10. Aug 2022, 21:09
Ich würde hier mit MMFs arbeiten. Durch das Mapping in den Arbeitsspeicher ist das extrem schnell. Damals kam ich bei einer normalen Festplatte auf 84 MiB/s, was heute mit einer SSD noch viel schneller gehen sollte.

Ich habe dafür einen Wrapper geschrieben:
https://www.delphipraxis.net/151898-...ei-reader.html

Flamefire hat sich das angeschaut und das ganze mit Streams umgesetzt:
https://entwickler-ecke.de/viewtopic.php?t=100088

Für die beste Performance musst du da vielleicht noch ein wenig schrauben, aber zumindest siehst du dort wie du mit MMFs arbeiten kannst.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Monday

Registriert seit: 24. Aug 2012
103 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Große Textdatei - einzelne Zeile löschen

  Alt 11. Aug 2022, 06:41
Kannst du mal bei Notepad++ das Plugin "BigFiles - Open Very Large Files" probieren? Würde mich interessieren, ob er das packt.
  Mit Zitat antworten Zitat
Benutzerbild von dummzeuch
dummzeuch

Registriert seit: 11. Aug 2012
Ort: Essen
1.468 Beiträge
 
Delphi 10.2 Tokyo Professional
 
#8

AW: Große Textdatei - einzelne Zeile löschen

  Alt 11. Aug 2022, 08:02
Ich hatte mal ein Tool zum Anschauen großer Textdateien geschrieben, das ich damals mit einem Dump der Wikipedia getestet hatte (damals 48 GB).

Funktionsweise war, dass es in einem Hintergrund-Thread die Datei liest und einen Index der Zeilenumbrüche bzw. Zeilenanfänge erzeugt, den es in eine Datei schreibt, so dass der Index nicht jedes Mal neu erzeugt werden muss.

Vielleicht findest Du ja im Sourcecode ein paar Anregungen?

Wichtig: Die Suchfunktion habe ich nie fertiggestellt, nicht dass Du dich wunderst, dass sie nicht funktioniert.
Thomas Mueller
  Mit Zitat antworten Zitat
freimatz

Registriert seit: 20. Mai 2010
1.380 Beiträge
 
Delphi 11 Alexandria
 
#9

AW: Große Textdatei - einzelne Zeile löschen

  Alt 11. Aug 2022, 08:54
Nun ist es ja so, dass man Dateien ab einer gewissen Größe nicht mal ebenso in einen Editor laden kann.
Notepad++, PilotEdit, PSPad, usw. machen da irgendwann schlapp! UltraEdit soll das angeblich können, aber da der Download der Demo nicht klappt, kann ich dazu wenig sagen!
Mal hier versucht Ultraedit, neueste Version, aber nur 50GByte und keine Textdatei sondern binär.
a) Nach einigen Minuten war er bei 50%, habe dann abgebrochen
b) Eine Option umgestellt, nochmals versucht, nach ca. 2 Sekunden war die Datei da.
Scrollen über die ganze Datei ist etwas hackelig, finde ich aber erstaunlich gut.
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
9.345 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Große Textdatei - einzelne Zeile löschen

  Alt 11. Aug 2022, 09:03
Ich würde das schlicht mit HxD machen, wenn es ein fertiges Programm sein soll. Dann fällt einiges weg, was ein Texteditor noch zusätzlich machen muss, und es muss wirklich nur die Änderung an der Datei geschrieben werden.
Sebastian Jänicke
Alle eigenen Projekte sind eingestellt, ebenso meine Homepage, Downloadlinks usw. im Forum bleiben aktiv!
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 3  1 23      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 21:15 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz