AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Eigenes Zeichen für Zeilenende bei ReadLN
Thema durchsuchen
Ansicht
Themen-Optionen

Eigenes Zeichen für Zeilenende bei ReadLN

Ein Thema von Ginko · begonnen am 21. Mai 2013 · letzter Beitrag vom 23. Mai 2013
Antwort Antwort
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#1

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 22. Mai 2013, 00:24
Das ist auch nicht weiter verwunderlich schickst du doch den FileStream immer wieder an das Ende der Datei und dann zurück an die aktuelle Leseposition (FileStrm1.Size ).

Darum solltest du dir die Größe des Streams zwischenspeichern, dann sollte das erheblich schneller vonstatten gehen

Delphi-Quellcode:
var
  FileStrm1: TFileStream;
  LStreamSize : Int64; // lokale Variable
  Ch: Char;
  GesLength: Integer;
  Gesucht,Seite: String;
  StrList1: TStringList;
begin
  Gesucht:= ( UTF8Decode( Edit1.Text ) );

  StrList1:= TStringList.Create;
  FileStrm1:= TFileStream.Create('Textdatei.txt',fmOpenRead);
  try
    GesLength:= 0;

    // Stream-Size merken
    LStreamSize := FileStrm1.Size;

    // und damit prüfen
    while FileStrm1.Position < LStreamSize do
    begin
      Seite := '';
      while (FileStrm1.Read(Ch, 1) = 1) and ( Ch <> #12 ) do //Seite in String speichern
        Seite := Seite + Ch;
       
      ...
      {Textsuche und weitere Auswertung, Ergebnisse in Stringlist speichern...}
      ...

      GesLength:= GesLength + SeitenLength + 1;
    end;

  finally
    FreeAndNil(StrList1);
    FreeAndNil(FileStrm1);
  end
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#2

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 22. Mai 2013, 07:11
Es wird 2x geprüft, ob noch Zeichen da sind, und zwar einmal beim Abfragen der Position und dann nochmal ob das Lesen eines Zeichens funktioniert hat. Das ist nicht schön.

Ich würde eine Funktion schreiben, die genau eine Seite liefert und True/False, ob noch weitere Seiten zu erwarten sind.

Delphi-Quellcode:
Function ReadOnePage (myFileStream : TStream; Var Page : String) : boolean;
Const
  CharSize = SizeOf(Char);
Var
  Ch : Char;

Begin
  result := True;
  Page := '';
  While myFileStream.Read(Ch,CharSize) = CharSize do
    if Ch=#12 then
      exit
    else
      Page := Page + Ch;

  result := false;
End;

// Der eigentliche Aufruf ist dann ziemlich selbsterklärend
While ReadOnePage (myFileStream, Page) Do
  ProcessPage(Page)
  Mit Zitat antworten Zitat
Ginko

Registriert seit: 30. Aug 2008
208 Beiträge
 
FreePascal / Lazarus
 
#3

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 22. Mai 2013, 09:05
@Furtbichler Danke für den Hinweis, allerdings konnte mit der Funktion keinen wesentlichen unterschied merken, auch ca 36s für die Suche von ca 2200 Wörtern.

Darum solltest du dir die Größe des Streams zwischenspeichern, dann sollte das erheblich schneller vonstatten gehen
Das werd ich mal noch versuchen Danke für die Antworten nochmal. Hab den Beitrag grad übersehen...

Geändert von Ginko (22. Mai 2013 um 09:10 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von jaenicke
jaenicke

Registriert seit: 10. Jun 2003
Ort: Berlin
10.055 Beiträge
 
Delphi 12 Athens
 
#4

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 22. Mai 2013, 11:11
Wie schon geschrieben, mit der MMF wie ich es mache, geht es natürlich deutlich schneller als zeichenweise aus der Datei selbst zu lesen.

Das Problem hatte ich als ich für einen Registryeditor die .reg Dateien einlesen wollte. Und dort konnte ich dann eine solche 350 MiB Datei in wenigen Sekunden komplett einlesen und parsen.
Sebastian Jänicke
AppCentral
  Mit Zitat antworten Zitat
Furtbichler
(Gast)

n/a Beiträge
 
#5

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 22. Mai 2013, 17:50
@Furtbichler Danke für den Hinweis, allerdings konnte mit der Funktion keinen wesentlichen unterschied merken, auch ca 36s für die Suche von ca 2200 Wörtern.
Das sollte auch nur den Code besser lesbar gestalten. Das Einlesen in einen Puffer, um ihn dann zeichenweise in einen zweiten zu kopieren, um dann in Selbigem zu suchen ist -nun ja- dezent suboptimal, würde ich sagen.

Wenn Du an der Performance herumschrauben willst, dann versuche mal, den Algorithmus zu verbessern. Ach, und nimm endlich Sebastian Jänicke's MMF-Teil.
  Mit Zitat antworten Zitat
Ginko

Registriert seit: 30. Aug 2008
208 Beiträge
 
FreePascal / Lazarus
 
#6

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 23. Mai 2013, 09:32
Das sollte auch nur den Code besser lesbar gestalten.
Ok das war ein Missverständnis, besser lesbar wird er so ja.

Ach, und nimm endlich Sebastian Jänicke's MMF-Teil.
aye aye, sir

Den Teil hatte ich schon ausprobiert, allerdings wollte ich das "kleine Problem" nicht gleich mit einer neuen Unit erschlagen. Muss man auch nicht wenn man bauminas ersten Vorschlag etwas anpasst, dann hat man eine schnelle und einfache Lösung.
Gut Jänicke's MMF-Teil ist noch ein wenig schneller, aber da habe ich auch noch ein Problem mit. Ich habe den Delimiter auf #12 gestellt um die Seiten ganz zu erfassen. Schaut man sich die Zeile (bzw. Seite) im Debugger an, fehlt allerdings das erste Zeichen einer Zeile (bzw. Seite) im zweiten Durchlauf. Das liegt sicher daran das ja sonst die zwei Zeichen #13#10 benutzt werden. Gibt es da noch eine Option die ich übersehen habe oder muss man was umschreiben ?

Geändert von Ginko (23. Mai 2013 um 09:56 Uhr)
  Mit Zitat antworten Zitat
Ginko

Registriert seit: 30. Aug 2008
208 Beiträge
 
FreePascal / Lazarus
 
#7

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 23. Mai 2013, 14:56
Hier ist mal noch die Variante für ReadLn, angepasst mit der Struktur ähnlich der von Furtbichler. Es gibt jetzt von der Geschwindigkeit keinen Unterschied mehr zur MMF-Klasse, jedenfalls für meine Anwendung.
Testdatei: 56MB Text
ReadLn Version: 3141349 Funde, Zeit: 1468ms
MMF-Klasse Version: 3139069 Funde, Zeit: 1438ms (wegen oben beschriebenen Problems weniger Funde, deshalb wahrscheinlich auch hier minimal schneller)
Delphi-Quellcode:
function EineSeiteLesen(var pDateiname: TextFile; var pSeite : String; var pZeile: String): Boolean;
begin
  Result:= True;
  pSeite:= '';
  if pZeile <> 'then pSeite:= pZeile; //Rest aus dem vorherigen Durchlauf
  while not EOF(pDateiname) do
  begin
    ReadLn(pDateiname,pZeile);
    if Pos(#12,pZeile) > 0 then
    begin
      Delete(pZeile,1,1);
      Exit;
    end
    else
      pSeite:= pSeite + pZeile + #13#10;
  end;

  Result:= False;
end;
(Textbuffer steht auf 1024*1024)

Geändert von Ginko (23. Mai 2013 um 15:41 Uhr)
  Mit Zitat antworten Zitat
Bjoerk

Registriert seit: 28. Feb 2011
Ort: Mannheim
1.384 Beiträge
 
Delphi 10.4 Sydney
 
#8

AW: Eigenes Zeichen für Zeilenende bei ReadLN

  Alt 23. Mai 2013, 17:00
Hab' ne Klasse von "früher", wo ich auch viel mit Textfiles gearbeitet habe. Mal eben auf Sebastian’s TSJMmfFileReader Standard gebracht. Mit SSD Festplatte 1,2 sec. für das Einlesen der letzten Seite einer 300 MB Textdatei (Kompliment an Sebastian!). Mit AssignFile und Co (Textbuffer 4K) 2 sec.
Delphi-Quellcode:
function LoadSinglePageFromFile(FileName: string; SinglePage: TStringList;
  Index: integer): boolean; // Index = 0 .. PagesCount - 1
const
  cFormFeed = #12; // ^L PageBreak
var
  FileReader: TSJMmfFileReader;
  CurrentReadString: string;
  NewPage: boolean;
  ReadPagesCount: integer;
begin
  Result := false;
  if FileExists(FileName) then
  begin
    SinglePage.Clear;
    FileReader := TSJMmfFileReader.Create(FileName);
    ReadPagesCount := 0;
    try
      while (FileReader.Position < FileReader.Size)
        and (ReadPagesCount <= Index) do
      begin
        FileReader.Readln(CurrentReadString);
        NewPage := Pos(cFormFeed, CurrentReadString) = 1; // ***
        if NewPage then
        begin
          Inc(ReadPagesCount);
          if ReadPagesCount = Index then
          begin
            System.Delete(CurrentReadString, 1, 1);
            if CurrentReadString <> 'then
              SinglePage.Add(CurrentReadString);
          end;
        end
        else
          if ReadPagesCount = Index then
            SinglePage.Add(CurrentReadString);
      end;
      Result := true;
    finally
      FileReader.Free;
    end;
  end;
end;
  Mit Zitat antworten Zitat
Antwort Antwort


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 03:02 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz