Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Object-Pascal / Delphi-Language (https://www.delphipraxis.net/32-object-pascal-delphi-language/)
-   -   Delphi bestimmten Bereich einer Textdatei auslesen (https://www.delphipraxis.net/67108-bestimmten-bereich-einer-textdatei-auslesen.html)

shadowman 9. Apr 2006 18:51


bestimmten Bereich einer Textdatei auslesen
 
Hallo zusammen,
ich möchte einen bestimmten Bereich (bestimmte Anzahl Zeilen) einer Textdatei in eine StringList einlesen. Ich habe zur verfügung:
Fall 1:
- den Anfang des Bereiches in Bytes
- das Ende des Bereiches in Bytes
- die Länge des Bereiches in Bytes

so wie

Fall 2:
- den Anfang des Bereiches als Zeilennummer
- das Ende des Bereiches als Zeilennummer
- die Länge des Bereiches in Bytes (hier nicht unbedingt nötig vermutlich)


Im Fall 1 müsste man es mit BlockRead machen laut meiner Recherchen, allerdings bekomme ich das nicht hin. Ich bekomme beim Aufruf von BlockRead die Fehlermeldung "E/A-Fehler 998." (Unzulässiger Zugriff auf einen Speicherbereich).

hier der Code:

Delphi-Quellcode:
var
   f: file;
   aktMail: TStringList;
begin
   aktMail := TStringList.Create;
   
   try
      AssignFile(f, <meine Datei>);
      Reset(f,1);
      Seek(f, <der Anfang in Bytes>);
      BlockRead(f, aktMail, <zu lesende Länge>);
    ...
    ...
   finally
      FreeAndNil(aktMail);
   end;
end;
Es gibt viele Fälle im Netz, wo das Thema behandelt wird, aber ich bin daraus leider nicht schlau geworden.
Ist dieser Weg zur Lösung meines Problems überhaupt zu gebrauchen? Wenn ja, würde ich gerne wissen wie das geht.


Im zweiten Fall könnte ich einfach mir ReadLn den Bereich zwischen der Anfangs- und Endzeile einlesen, nur weiß ich nicht, wie ich in der Textdatei zu einer bestimmten Zeile (Anfangszeile) "springen" kann. Seek funktioniert in dem Fall nicht, wenn ich mich nicht irre.

Wie bekomme ich also am besten einen bestimmten Bereich einer Textdatei in eine StringList eingelesen?

Gruß,
shadow

marabu 9. Apr 2006 19:14

Re: bestimmten Bereich einer Textdatei auslesen
 
Für Fall 1 ist die Lösung recht einfach:

Delphi-Quellcode:
function LoadStringFromFile(fn: TFileName; iOffset, iSize: Cardinal): String;
begin
  with TFileStream.Create(fn, fmOpenRead) do
  try
    Position := iOffset;
    SetLength(Result, iSize);
    Read(Result[1], iSize);
  finally
    Free;
  end;
end;

var
  s: TStringList;
  iOffset, iSize: Cardinal;
  fn: TFileName;

begin
  s.Text := LoadStringFromFile(fn, iOffset, iSize);
end;
Grüße vom marabu

Hawkeye219 9. Apr 2006 20:57

Re: bestimmten Bereich einer Textdatei auslesen
 
Für Fall 2 gibt es mehrere mögliche Lösungen:

1.) Falls die Datei nicht allzu groß ist, könntest Du sie komplett in eine Stringliste einlesen (Methode LoadFromFile) und anschließend die nicht benötigten Zeilen löschen.
Da dies nur zeilenweise möglich ist, könnte es durch die zahlreichen Stringoperationen schnell zu größeren Laufzeiten kommen.

2.) Alternativ zur Stringliste kannst Du die Datei auch in einen String einlesen (wie in marabus Beispiel). In diesem String suchst Du den n-ten Zeilenvorschub (n = Startzeile - 1). Als Suchfunktion bietet sich z.B. GetPosNumX aus der DP an. Da die Länge des gewünschten Bereichs ja bekannt ist, kannst Du diesen schließlich über die Copy-Funktion extrahieren und der Stringliste zuweisen.

3.) Bei sehr großen Textdateien mußt Du möglicherweise blockweise vorgehen. Dazu wird die Datei als FileStream geöffnet, aus dem immer wieder ein Block (z.B. 16 KByte) in einen Puffer geladen wird. In jedem geladenen Block zählst Du die Zeilenvorschübe. Laden und Zählen wiederholst Du so lange, bis Du den gewünschten Zeilenvorschub gefunden hast; problematisch wird es dabei nur dann, wenn sich der Zeilenvorschub auf zwei Blöcke verteilt. Aus der Fundstelle und der Anzahl der gelesenen Blöcke kannst Du schließlich die absolute Position des Zeilenvorschubs in der Datei errechnen und mit der von marabu beschriebenen Lösung den gewünschten Bereich einlesen.

Für die meisten Dateien dürfte wohl die zweite Lösung die beste sein.

Gruß Hawkeye

marabu 9. Apr 2006 21:44

Re: bestimmten Bereich einer Textdatei auslesen
 
Hier noch eine vierte Möglichkeit - solange TextFile noch unterstützt wird - allerdings nur getippt und nicht getestet:

Delphi-Quellcode:
procedure GetLines(fn: TFileName; s: TStrings; iStart, iCount: Cardinal);
const
  BUF_SIZE = 16 shl 10;
var
  tf: TextFile;
  buf: array of Char;
  iLine: Cardinal;
  line: String;
begin
  SetLength(buf, BUF_SIZE);
  AssignFile(tf, fn);
  Reset(tf);
  SetTextBuf(tf, buf[0], BUF_SIZE);
  iLine := 0;
  while not Eof(tf) and (iLine < iStart) do
  begin
    ReadLn(tf);
    Inc(iLine);
  end;
  s.BeginUpdate;
  while not Eof(tf) and (iCount > 0) do
  begin
    ReadLn(tf, line);
    s.Add(line);
    Dec(iCount);
  end;
  s.EndUpdate;
  CloseFile(tf);
end;
Gute Nacht

marabu

shadowman 10. Apr 2006 13:52

Re: bestimmten Bereich einer Textdatei auslesen
 
hallo marabu, hallo Hawkeye,

vielen Dank für Eure Hilfe und Tipps.
Habe es jetzt so gemacht wie im ersten Vorschlag von marabu und es funktioniert alles prima.
Danke.

Gruß,
shadow


Alle Zeitangaben in WEZ +1. Es ist jetzt 16:23 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