Einzelnen Beitrag anzeigen

Delphi.Narium

Registriert seit: 27. Nov 2017
2.490 Beiträge
 
Delphi 7 Professional
 
#13

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

  Alt 11. Aug 2022, 15:23
Mal so JustForFun eine Variante mit FileStream und den alten Dateifunktionen aus Pascalzeiten.
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls, IniFiles;

type
  rFile = record
    AFile : TextFile;
    AFileName : String;
  end;

  TFiles = Array[32..255] of rFile;

type
  TForm1 = class(TForm)
    btnOpen: TButton;
    btnDoIt: TButton;
    btnCancel: TButton;
    btnClose: TButton;
    btnEnde: TButton;
    stb: TStatusBar;
    procedure FormCreate(Sender: TObject);
    procedure btnOpenClick(Sender: TObject);
    procedure btnDoItClick(Sender: TObject);
    procedure btnCancelClick(Sender: TObject);
    procedure btnCloseClick(Sender: TObject);
    procedure btnEndeClick(Sender: TObject);
  private
    { Private-Deklarationen }
    fInputFile : String;
    fOutputFiles : String;
    fPosition : Int64;
    fFiles : TFiles;
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

// Das sollte man sinnvollerweise in eine INI-Datei schreiben.
const
  csInputFile = 'I:\rockyou2021.txt';
  csOutputFiles = 'I:\rockyou2021-%.3d.txt';
  ciPosition = 0;

procedure TForm1.FormCreate(Sender: TObject);
var
  Ini : TIniFile;
begin
  Ini := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  fInputFile := Ini.ReadString('Config','InputFile',csInputFile);
  fOutputFiles := Ini.ReadString('Config','OutputFiles',csOutputFiles);
  fPosition := Ini.ReadInteger('Config','Position',ciPosition);
  Ini.Free;
end;

procedure TForm1.btnOpenClick(Sender: TObject);
var
  i : Integer;
begin
  Screen.Cursor := crHourGlass;
  if fInputFile = 'then fInputFile := csInputFile;
  if fOutputFiles = 'then fOutputFiles := csOutputFiles;
  if fPosition < 0 then fPosition := ciPosition;
  for i := Low(fFiles) to High(fFiles) do begin
    fFiles[i].AFileName := Format(fOutputFiles,[i]);
    AssignFile(fFiles[i].AFile,fFiles[i].AFileName);
    case FileExists(fFiles[i].AFileName) of
      true : Append(fFiles[i].AFile);
      false : ReWrite(fFiles[i].AFile);
    end;
  end;
  btnDoIt.SetFocus;
  Screen.Cursor := crDefault;
end;

procedure TForm1.btnDoItClick(Sender: TObject);
var
  input : TFileStream;
  ch : Char;
  sZeile : String;
  iZeilen : Integer;
  dtStart : TDateTime;
  dtEnde : TDateTime;
  dtLaufzeit : TDateTime;
  dProzent : Double;
begin
  Screen.Cursor := crHourGlass;
  btnCancel.SetFocus;
  btnCancel.Tag := 0;
  dtStart := Now;
  sZeile := '';
  iZeilen := 0;
  input := TFileStream.Create(fInputFile,fmOpenRead);
  input.Seek(fPosition, soFromBeginning);
  if input.Read(ch, 1) > 0 then begin
    repeat
      case ch of
        #10 : begin
                if sZeile <> 'then WriteLn(fFiles[Ord(sZeile[1])].AFile,sZeile);
                sZeile := '';
                iZeilen := iZeilen + 1;
                if iZeilen mod 10000 = 0 then begin
                  dProzent := input.Position * 100 / input.Size;
                  dtLaufzeit := Now - dtStart;
                  dtEnde := dtStart + (dtLaufzeit * 100 / dProzent);
                  stb.SimpleText := Format('Zeilen: %d - Position: %d von %d (%.2f%% - Ende ca.: %s)',
                                    [iZeilen,input.Position,input.Size,dProzent,DateTimeToStr(dtEnde)]);
                  Application.ProcessMessages;
                  if btnCancel.Tag <> 0 then break;
                end;
              end;
        #13 : begin end;
      else
        sZeile := sZeile + ch;
      end;
    until (input.Read(ch, 1) = 0);
  end;
  fPosition := input.Position;
  dtEnde := Now - dtStart;
  Screen.Cursor := crDefault;
  ShowMessage(Format('Zeilen: %d%sLaufzeit: %s%sPosition: %d',
              [iZeilen,sLineBreak,TimeToStr(dtEnde),sLineBreak,input.Position]));
  input.Free;
  btnClose.SetFocus;
end;

procedure TForm1.btnCancelClick(Sender: TObject);
begin
  btnCancel.Tag := 1;
end;

procedure TForm1.btnCloseClick(Sender: TObject);
var
  i : Integer;
begin
  Screen.Cursor := crHourGlass;
  for i := Low(fFiles) to High(fFiles) do CloseFile(fFiles[i].AFile);
  btnEnde.SetFocus;
  Screen.Cursor := crDefault;
end;

procedure TForm1.btnEndeClick(Sender: TObject);
var
  Ini : TIniFile;
begin
  Ini := TIniFile.Create(ChangeFileExt(Application.ExeName,'.ini'));
  Ini.WriteString('Config','InputFile',fInputFile);
  Ini.WriteString('Config','OutputFiles',fOutputFiles);
  Ini.WriteInteger('Config','Position',fPosition);
  Ini.Free;
  Close;
end;

end.
Inidatei dazu:
Code:
[Config]
InputFile=I:\rockyou2021.txt
OutputFiles=I:\rockyou2021-%.3d.txt
Position=0
Damit sollte es möglich sein, die Verarbeitung und Aufteilung einer Datei zu starten, beliebig zu unterbrechen und zu einem späteren Zeitpunkt an der Stelle zur Weiterverarbeitung aufzusetzen, an der die vorherige Verarbeitung abgebrochen wurde.

Testdaten:

Dateigröße: 199.526.693 Byte
Zeilen : 3.225.774
Laufzeit : 00:18:11

Festplatte: extern USB 2
Rechner : Dell Optiplex GX620
PentiumR 2 x 2,80 GHZ, 1GB RAM

Hochgerechnet auf 97 GB: ca. 6 bis 7 Tage Laufzeit

Bei einem zeitgemäßen System könnte die Laufzeit durchaus kürzer ausfallen
  Mit Zitat antworten Zitat