Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Programmieren allgemein (https://www.delphipraxis.net/40-programmieren-allgemein/)
-   -   Eigenes Zeichen für Zeilenende bei ReadLN (https://www.delphipraxis.net/174953-eigenes-zeichen-fuer-zeilenende-bei-readln.html)

Ginko 21. Mai 2013 11:47

Eigenes Zeichen für Zeilenende bei ReadLN
 
Hallo,
Gibt es eine Möglichkeit das Zeichen, welches ein Zeilenende markiert, selbst zu bestimmen.
Es geht dabei um das Zeilenweise einlesen einer Textdatei mit ReadLn. Also ich meine so etwas wie SetLineBreakStyle nur für ein eigenes Zeichen. (Die Textdatei ist sehr groß deshalb wollte ich zeilenweise einlesen)

Luckie 21. Mai 2013 11:52

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Besteht die Datei denn aus einer einzigen Zeile oder wie?

Ginko 21. Mai 2013 11:56

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Nein, es sind mehrere Seiten in einer Textdatei (ein paar tausend Seiten), die ich gerne jeweils einzeln einlesen würde . Die Seiten haben auch LineBreaks aber ich möchte immer eine Seite komplett laden. Deshalb habe ich gedacht ich markiere Anfang unde ENde einer Seite mit einem speziellen Zeichen, welches dann als Anfang bzw. Ende des Buffers gilt, der mit ReadLn eingelesen wird.

baumina 21. Mai 2013 12:19

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
kann man sich die Datei ungefähr so vorstellen?
Code:
Zeile1#13#10
Zeile2#13#10
Zeile3#13#10
EndeSeite$#13#10
Zeile4#13#10
Dann würde ein readln Zeile1 liefern, weiteres readln Zeile2 usw. Wenn Du dann im readln-gelieferten String nachschaust ob ein z.B. "$" am Ende vorkommt, dann wäre die Seite zuende und Du könntest einen neuen Buffer machen.

Ginko 21. Mai 2013 12:32

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
doppelpost sorry

Ginko 21. Mai 2013 12:34

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Danke für die Antworten !
Ja so könnte eine Seite aussehen.
Zitat:

Zitat von baumina (Beitrag 1215923)
Dann würde ein readln Zeile1 liefern, weiteres readln Zeile2 usw. Wenn Du dann im readln-gelieferten String nachschaust ob ein z.B. "$" am Ende vorkommt, dann wäre die Seite zuende und Du könntest einen neuen Buffer machen.

Stimmt so könnte ich es machen.

Wäre es auch möglich ReadLn umzuschreiben (also ein eigenes ReadLn zu schreiben) und wäre das dann schneller im einlesen, wenn man nur das entprechende Zeichen einsetzt ?

baumina 21. Mai 2013 13:51

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Wenn du es nicht über ein definiertes Seitenende-Zeichen lösen willst, wäre TFileStream auch noch interessant. Damit könntest du die Blockgröße angeben, die du lesen magst.

Perlsau 21. Mai 2013 14:08

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Also irgendwie verstehe ich die Diskussion nicht so ganz. Wofür benötigt man ein extra Zeichen für Zeilenende, wenn doch bereits eines vorhanden ist? Dann schreibt Baumina plötzlich von einem Zeichen für das Seitenende, was aber von Ginko offenbar übersehen wird, hatte er doch nach dem Zeilenende gefragt, und Baumina schreibt weiterhin lustig vom Seitenende ... Wäre nett, wenn du, Ginko, einmal darüber aufklärst, ob du wirklich Zeilenende meintest oder doch Seitenende ...

Zitat:

Zitat von Ginko (Beitrag 1215916)
Gibt es eine Möglichkeit das Zeichen, welches ein Zeilenende markiert, selbst zu bestimmen.

Zitat:

Zitat von baumina (Beitrag 1215932)
Wenn du es nicht über ein definiertes Seitenende-Zeichen lösen willst, wäre TFileStream auch noch interessant.

@Ginko: Woher stammt denn der Ursprungstext? Word? OpenOffice? PDF? Ich glaube nämlich nicht, daß du einfach z.B. das von Word generierte Zeilen- oder Absatzende-Zeichen umdefinieren kannst. Wieso sollte eine Textdatei mit einem anderen Zeilenende-Zeichen schneller einlesbar sein?

Und vor allem: Wieso nimmst du nicht einfach eine Stringliste zum Einlesen? Das geht so saumäßig schnell, daß dir die Spucke wegbleibt :wink:

Ginko 21. Mai 2013 14:28

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Die Textdatei resultiert aus der Umwandlung einer PDF-Datei in Text und sieht wie folgt aus.
Code:
Zeilentext #13#10
Zeilentext #13#10
...
§Zeilentext #13#10
Zeilentext #13#10
...
§Zeilentext #13#10
Zeilentext #13#10
...
Wobei hier § (in wirklichkeit ist es #12) einen neuen Seitenanfang kennzeichnet (der urspr. PDF-Datei).
Ich glaube baumina hat es auch richtig verstanden, allerdings gibt es bei mir (mit obiger Lösung) noch das Problem das hinter dem § Zeichen noch der Rest mitübernommen wird (§Zeilentext #13#10).

Uwe Raabe 21. Mai 2013 14:29

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215916)
(Die Textdatei ist sehr groß deshalb wollte ich zeilenweise einlesen)

Was ist denn bei dir "sehr groß"?

Ginko 21. Mai 2013 14:33

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Also wenn sie fertig ist sollte sie so an die 200Mb sein. Vielleicht eher nur groß ...
Stringliste sollte dann rausfallen...

Bernhard Geyer 21. Mai 2013 14:45

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
ReadLn dürft doch schon auf der Liste der gefährdeten Funktionen stehen.
Sie sind eh eingeschränkt (Kein Unicode-Support), Verursachen teilweise komische Fehler (umstellung auf TFileStream und Co-Methoden haben die Fehler verschwinden lassen) und könnten im Rahmen des zukünftigen LLV-Compilerprojektes entfernt werden.

Ginko 21. Mai 2013 14:51

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Ist es bei TFileStream und Co-Methoden auch möglich mit Textdateien so zu arbeiten, dass nicht die ganze Datei in den Speicher geladen wird ?

Sir Rufo 21. Mai 2013 14:54

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215941)
Ist es bei TFileStream und Co-Methoden auch möglich mit Textdateien so zu arbeiten, dass nicht die ganze Datei in den Speicher geladen wird ?

Ein Delphi-Referenz durchsuchenTStream ist erst einmal nur eine Ansammlung von zusammenhängenden Bytes, die z.B. in einer Datei Delphi-Referenz durchsuchenTFileStream liegen oder im Speicher Delphi-Referenz durchsuchenTMemoryStream.

Ginko 21. Mai 2013 15:05

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Delphi-Quellcode:
var
  FileStrm1: TFileStream;
  tmpStr1, SuchWort: String;
  len: Cardinal;
  startpos: Integer ;
begin
  FileStrm1:= TFileStream.Create(Dateiname,fmOpenRead or fmShareCompat);
  try
    SuchWort:= Edit2.Text
    SetLength(tmpStr1, Length(SuchWort));
    startpos:= StrToInt(Edit3.Text);

    FileStrm1.Seek(startpos,soFromBeginning);
    FileStrm1.ReadBuffer(tmpStr1[1], Length(tmpStr1));

    ShowMessage('Wort: ' + tmpStr1 +' || Position: ' +IntToStr(FileStrm1.Position));
  finally
    FreeAndNil(FileStrm1);
  end;
Also bei diesem Vorgang würde der Speicher nur um ca. die größe von tmpStr1 anwachsen ?

Perlsau 21. Mai 2013 15:06

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215935)
Die Textdatei resultiert aus der Umwandlung einer PDF-Datei in Text und sieht wie folgt aus.
Code:
Zeilentext #13#10
Zeilentext #13#10
...
§Zeilentext #13#10
Zeilentext #13#10
...
§Zeilentext #13#10
Zeilentext #13#10
...
Wobei hier § (in wirklichkeit ist es #12) einen neuen Seitenanfang kennzeichnet (der urspr. PDF-Datei).
Ich glaube baumina hat es auch richtig verstanden, allerdings gibt es bei mir (mit obiger Lösung) noch das Problem das hinter dem § Zeichen noch der Rest mitübernommen wird (§Zeilentext #13#10).

Mir ist noch immer nicht so recht klar, was du eigentlich mit dem Text zu tun beabsichtigst. Nehmen wir einmal an, du liest deine Textdatei via Stringliste ein:
Delphi-Quellcode:
procedure TForm1.TextEinlesen(Datei: String; Liste: TStrings);
begin
   if FileExists(Datei) then
   Liste.LoadFromFile(Datei) else
   ShowMessage('Die Datei existiert nicht.');
end;
Danach hast du in der zurückgelieferten Stringliste die ganze Textdatei. Nun kannst du die bearbeiten: z.B. Nach Seiten-Ende-Zeichen suchen und gegebenenfalls einen leeren Absatz in deine Darstellungskomponente (Memo, RichEdit) einfügen. Ein Zeilen-Ende-Zeichen benötigst du nicht extra, das ist ja schon in der Textdatei enthalten. Wenn du eigentlich Seiten-Ende statt Zeilen-Ende gemeint hattest, solltest du das auch mitteilen. Aber auch Seiten-Ende-Zeichen scheinen in deiner Datei bereits vorhanden zu sein. Ehrlich gesagt, ich verstehe dein Problem nicht. Oder besser: Schreib doch einmal genau, was dir Probleme macht.

Ginko 21. Mai 2013 15:16

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Es soll auf der Seite im Text gesucht werden, allerdings benötige ich zum Suchergebnis zusätzlich Informationen, die am Ende einer Seite stehen, dehalb soll immer eine ganze Seite eingelesen werden.

Ich habe es jetzt erstmal so gelöst das ich einfach mal alle Linebreaks mit StringReplace gelöscht habe und nur das § Zeichen (bzw #12) durch einen Linebreak ersetzt habe. Allerdings geht mir dann die ursprüngliche Strukur verloren...

Perlsau 21. Mai 2013 15:16

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215937)
Also wenn sie fertig ist sollte sie so an die 200Mb sein. Vielleicht eher nur groß ...
Stringliste sollte dann rausfallen...

Auch das verstehe ich nicht: Was meinst du mit "Stringliste rausfallen"?

Luckie 21. Mai 2013 15:18

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Er ist wohl der Meinung, dass eine StringListe für so große Dateien nicht geeignet wäre.

Ginko 21. Mai 2013 15:20

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Dann hätte ich 200MB Speicherverbrauch wenn ich die ganze Datei in eine Stringlist laden würde...

Luckie 21. Mai 2013 15:23

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Ja und? Wozu hast du denn den Speicher in deinem Rechner? Ich meine, du kannst das ganze natürlich mit MemoryMappedFiles lösen, aber wozu der Aufwand in Gefilden von 200 bis 300 MB?

Meine Idee:
1. Lade Datei in StringListe
2. Gehe die Zeilen der StringListe durch
3. Wenn am Anfang einer Zeile kein "$" gefunden, dann kopiere die Zeile in eine zweite StringListe
4. Wenn am Anfang einer Zeile "$" gefunden (Jetzt weiß ich nicht, was mit dieser Zeile passieren soll. Das musst du wissen.), dann speichere die zweite StringListe ab, ode rmach was mit ihrem Inhalt
5. Wenn das geschehen gehe die Zeilen der ersten StringListe weiter durch
6. goto 3

Perlsau 21. Mai 2013 15:24

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215948)
Es soll auf der Seite im Text gesucht werden, allerdings benötige ich zum Suchergebnis zusätzlich Informationen, die am Ende einer Seite stehen, dehalb soll immer eine ganze Seite eingelesen werden.

Es soll also immer nur auf einer Seite gesucht werden? Wieso denn das? Möchtest du nicht im gesamten Textdokument nach deinem gesuchten Text fahnden?

Zitat:

Zitat von Ginko (Beitrag 1215948)
Ich habe es jetzt erstmal so gelöst das ich einfach mal alle Linebreaks mit StringReplace gelöscht habe und nur das § Zeichen (bzw #12) durch einen Linebreak ersetzt habe. Allerdings geht mir dann die ursprüngliche Strukur verloren...

Na ist doch klar: Wenn du die Struktur eines Textes zerstörst, dann geht sie verloren. Wenn's regnet, wird man naß ...

Ginko 21. Mai 2013 15:29

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Ja es soll im ganzen Text gesucht werden, Missverständnis.
Allerdings soll bei einem Fund, Informationen vom Ende der Seite (Seitenzahl etc.) an das Suchergebnis angehängt werden. Deshalb brauch ich bei ReadLn immer den Abschnitt bis zum Ende einer Seite... (Weil ich die Datei Zeilenweise durchsuche).

Meine obige Lösung mit Stringreplace ist nur ein Übergangslösung. Für die reine Suche reicht sie aber vollkommen.

Luckie 21. Mai 2013 15:34

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Hast du dir mal meinen Vorschlag näher angeguckt? Dann pack die Seitenende-Zeile noch mit in die zweite StringListe. Durchsuche die zweite StringListe und die zusätzlichen Informationen findest du dann immer in der letzten Zeile der zweiten StringListe.

Ginko 21. Mai 2013 15:36

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Ich schau mir das mal noch genauer an. Muss jetzt aber erstmal weg. Danke bis hier für die ANtworten.

nahpets 21. Mai 2013 15:40

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Hallo,

schau Dir bitte mal TFileStream genau an.

Dann liest Du damit "zeichenweise". Immer wenn Du auf #12 stößt, weißt Du, dass eine Seite zuende ist.

Ich versuche es mal mit Pseudocode:
Code:
erstelle eine Stringliste
erstelle einen Memorystream
erstelle einen Filestream
wiederhole
  lese ein Zeichen aus dem Filestream
  ist Zeichen = #12
    kopieren den memorystream in eine Stringliste
    // hier enthält die Stringliste nun genau eine Seite
      mache hier die erforderlichen Arbeiten für diese Seite
    leer Stringliste
    leere memeorystream
  ist Zeichen <> #12
    schreibe zeichen in memeorystream
wiederhole bis Dateiende
// Erforderlich für die letzte Seite, falls die nicht mit #12 enden sollte.
ist der Memorystream nicht leer
  kopieren den memorystream in eine Stringliste
  // hier enthält die Stringliste nun genau eine Seite
    mache hier die erforderlichen Arbeiten für diese Seite
Ende

jaenicke 21. Mai 2013 15:42

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Wie wäre es mit meinem entsprechenden Reader?
http://www.delphipraxis.net/151898-s...ei-reader.html
Eine .reg Datei dieser Größe habe ich damit inkl. Parsen in unter 5 Sekunden in einem Baum angezeigt bekommen.

Bernhard Geyer 21. Mai 2013 16:16

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1215953)
Dann hätte ich 200MB Speicherverbrauch wenn ich die ganze Datei in eine Stringlist laden würde...

Nein. Eher bis zu 600 MB

200 MB für die Datei und jedeils 2 Byte (Unicode) für jedes Zeichen während des Aufbaus der Ergebnisliste.
AFAIK arbeitet hier die Delphi-Implementierung nicht gerade Speicherschonend.

Perlsau 21. Mai 2013 16:40

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Luckie (Beitrag 1215951)
Er ist wohl der Meinung, dass eine StringListe für so große Dateien nicht geeignet wäre.

Vielleicht stimmt das ja auch:

Eben hatte ich einen Testdurchlauf gestartet mit einer ca. 285 MB großen Textdatei. Beim Versuch, diese Datei (nicht Zip einlesen, sondern vorher entpacken) direkt in eine Stringliste einzulesen, erhalte ich nach kurzer Zeit die Meldung, ich hätte zu wenig Arbeitsspeicher:
Exception der Klasse EOutOfMemory mit der Meldung 'Zu wenig Arbeitsspeicher' aufgetreten.
In meinem Rechner sind 4 GB Ram verbaut. Geöffnet sind ein Dateimanager, Seamonkey, Thunderbird und RadStudio 2009 nebst im Debug-Mode laufender Exe. Das kann's doch nicht sein :?:

Delphi-Quellcode:
procedure TForm1.Button_TextClick(Sender: TObject);
Var
   Liste : TStrings;

begin
     IF NOT OpenDlg.Execute THEN Exit;
     Liste := TStringList.Create;

     Try
       Liste.LoadFromFile(OpenDlg.FileName);
     Finally
       Liste.Free;
     End;
end;
Lese ich dagegen die Textdatei via ReadLn ein und weise dabei jedesmal der Stringliste die eingelesene Zeile zu, komme ich auf 7.654.474 Zeilen, die sich am Ende in der Stringliste befinden. Das verstehe ich nicht: Beim direkten Einlesen ist der Speicher angeblich zu klein, beim Zuweisen über ReadLn paßt's dann wieder rein ...
Delphi-Quellcode:
procedure TForm1.Button_TextClick(Sender: TObject);
Var
   Liste : TStrings;
   f    : TextFile;
   Zeile : String;
begin
     IF NOT OpenDlg.Execute THEN Exit;
     Liste := TStringList.Create;
     AssignFile(f,OpenDlg.FileName);
     Reset(f);

     Try
       WHILE NOT EOF(f) DO
       BEGIN
         ReadLn(f,Zeile);
         Liste.Append(Zeile);
         Label_Anzahl.Caption := IntToStr(Liste.Count);
         Application.ProcessMessages;
       END;
     Finally
       Liste.Free;
       CloseFile(f);
       Label_Anzahl.Caption := Label_Anzahl.Caption + ' ' + Zeile;
     End;
end;
Es erfolgt keine Fehlermeldung, alle Zeilen der Datei wurden in die Stringliste übertragen. Wie kann es also sein, daß beim direkten Befüllen der Stringliste eine Meldung erscheint, der Arbeitsspeicher würde nicht ausreichen?

Eben erhalte ich die Mitteilung, daß die erste Procedure mit Liste.LoadFromFile, wenn sie mit XE2 kompiliert wurde, fehlerfrei arbeitet.

Uwe Raabe 21. Mai 2013 17:55

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Perlsau (Beitrag 1215978)
In meinem Rechner sind 4 GB Ram verbaut. Geöffnet sind ein Dateimanager, Seamonkey, Thunderbird und RadStudio 2009 nebst im Debug-Mode laufender Exe. Das kann's doch nicht sein :?:

Erstmal hat eine 32-Bit-Anwendung nur maximal 2GB Speicher zur Verfügung und dann getht TStringList.LoadFromFile da schon ziemlich verschwenderisch mit dem Speicher um. Die Datei hat knapp 300MB, die zunächst als TBytes geladen werden. Dann schlägt das Encoding zu, das da nochmal die doppelte Menge drauf legt (wegen Unicode) und die Zeichen in einem Character Array ablegt (sind dann schon fast 900MB). Das nachfolgende Erzeugen des Unicodestring (600MB) schlägt dann fehl, weil offenbar der Speichermanager nicht mehr mitspielt (VirtualAlloc schlägt fehl).

Als 64-Bit funktioniert es dann aber.

Man könnte jetzt natürlich TStringList ableiten, LoadFromStream überschreiben und für große Dateien effizienter implementieren.

Perlsau 21. Mai 2013 18:16

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Hallo Uwe, da hab ich wieder was dazugelernt :!: Dafür danke ich dir :thumb:

Zitat:

Zitat von Uwe Raabe (Beitrag 1215981)
Als 64-Bit funktioniert es dann aber.

Hab mir eben mal kurz Lazarus installiert, mit dem der TE ja offenbar arbeitet:

Das war ein Irrtum, ich hatte es in XP-64 gestestet:
Zitat:

Dort gibt es keine Fehlermeldung, wenn ich dieselbe Datei mit LoadFromFile in eine Stringlist lade, und das auf XP Pro 32. Ergo könnte er doch zumindest eine Stringlist verwenden, um seine 200 MB-Datei einzulesen. Da scheint Lazarus gegenüber Delphi was voraus zu haben ... Allerdings scheint Lazarus Probleme mit Unicode-Dateien zu haben ... Naja, sei's drum, ich will da jetzt nicht tiefer einsteigen in die Programmierung mit Lazarus.
Unter XP-32 taucht dieselbe Fehlermeldung auch unter Lazarus auf ...

Zitat:

Zitat von Uwe Raabe (Beitrag 1215981)
Man könnte jetzt natürlich TStringList ableiten, LoadFromStream überschreiben und für große Dateien effizienter implementieren.

Wer das kann? Mir wäre das zuviel an Aufwand ...

jaenicke 21. Mai 2013 19:13

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Perlsau (Beitrag 1215982)
Zitat:

Zitat von Uwe Raabe (Beitrag 1215981)
Man könnte jetzt natürlich TStringList ableiten, LoadFromStream überschreiben und für große Dateien effizienter implementieren.

Wer das kann? Mir wäre das zuviel an Aufwand ...

Naja, für LoadFromFile im Grunde meine Unit zum Einlesen und intern noch das Arrayhandling verbessern, das wars schon. Also so viel ist das nicht.

Ginko 21. Mai 2013 21:54

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
So ich habs mal mit dem Filestream gemacht. Das geht gar nicht, also von der Geschwindgkeit her ...
Bei einer Textdatei von 8Mb brauchte das ca 36s, mit ReadLn und angepassten TextBuffer hingegen nur ca 65ms.
Delphi-Quellcode:
var
  FileStrm1: TFileStream;
  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;

    while FileStrm1.Position < FileStrm1.Size 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
Ich werde mir noch die Klasse von jaenicke ansehen. Danke für den Hinweis.

hathor 21. Mai 2013 23:12

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Wenn die Textstruktur erhalten bleiben soll, muss man es auch so einlesen:
- zeilenweise vom Zeilenanfang bis Zeilenende #13#10
- seitenweise bis zum 1. Auftreten von #12, dann vom 1.Zeichen nach #12 bis zum nächsten #12 usw.

Steuerzeichen:
0001100,0xc,12,FF=Form Feed - Setzt Cursor auf Zeilenvorschub einer vorangegangenen Zeile

Sir Rufo 22. Mai 2013 00:24

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
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 (
Delphi-Quellcode:
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

Furtbichler 22. Mai 2013 07:11

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
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)

Ginko 22. Mai 2013 09:05

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
@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.

Zitat:

Zitat von Sir Rufo (Beitrag 1216003)
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...

jaenicke 22. Mai 2013 11:11

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
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.

Furtbichler 22. Mai 2013 17:50

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Ginko (Beitrag 1216016)
@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.

Ginko 23. Mai 2013 09:32

AW: Eigenes Zeichen für Zeilenende bei ReadLN
 
Zitat:

Zitat von Furtbichler (Beitrag 1216099)
Das sollte auch nur den Code besser lesbar gestalten.

Ok das war ein Missverständnis, besser lesbar wird er so ja.

Zitat:

Zitat von Furtbichler (Beitrag 1216099)
Ach, und nimm endlich Sebastian Jänicke's MMF-Teil.

aye aye, sir :mrgreen:

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 ?


Alle Zeitangaben in WEZ +1. Es ist jetzt 04:48 Uhr.
Seite 1 von 2  1 2      

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