Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi Zeilen in einer Datei zählen (https://www.delphipraxis.net/69790-zeilen-einer-datei-zaehlen.html)

happyaura 19. Mai 2006 23:06


Zeilen in einer Datei zählen
 
Hallo,
gibt es eine einfache möglichkeit, rauszubekommen, wieviele zeilen eine datei hat? Es handelt sich dabei um recht kurze zeilen, aber bis ca 65000 stück.

MFG Martin

Hawkeye219 19. Mai 2006 23:09

Re: Zeilen in einer Datei zählen
 
Hallo Martin,

am einfachsten dürfte es sein, die Datei in eine TStringList zu laden und deren Eigenschaft Count abzufragen.

Gruß Hawkeye

himitsu 19. Mai 2006 23:18

Re: Zeilen in einer Datei zählen
 
Oder so:
Delphi-Quellcode:
Var F: TextFile;
  Count: Integer;

Count := 0;
AssignFile(F, ...);
FileMode := fmOpenRead;
Reset(F);
While not EoF(F) do Begin
  ReadLn(F);
  Inc(Count);
End;
CloseFile(F);

Hansa 19. Mai 2006 23:52

Re: Zeilen in einer Datei zählen
 
Noch eine Möglichkeit : Dateigröße durch Länge der Zeilen teilen. Geht allerdings nur richtig, sofern alle Zeilen gleich lang sind !

happyaura 20. Mai 2006 00:04

Re: Zeilen in einer Datei zählen
 
Vielen Dank für die Antworten.
zeilen sind nicht exakt gleich lang, können um 1-2 zeichen vareieren. ich hab mich jetzt für die TStringlist entschieden, hab aber noch 'ne frage, ob ich so speicher verliere:

Delphi-Quellcode:
fileData := TStringList.Create;    
  for i := 1 to 8 do
  begin
    IF FileExists(filename[i]) then
    begin
      fileData.LoadFromFile(filename[i]);
      count[i]:=filedata.Count;
    end
    else
      count[i]:=0;
  end;
  filedata.Destroy;
die stinglist wird so ja 8 mal mit werten gefüllt. aber was passiert mit dem allokierten speicher der vorhergehenden einträge?
Gruß Martin

Hawkeye219 20. Mai 2006 00:10

Re: Zeilen in einer Datei zählen
 
Der Speicher sollte beim erneuten Füllen wieder freigegeben werden.

PS: Schon mal die Online-Hilfe zu Delphi-Referenz durchsuchenTObject.Destroy gelesen?

Gruß Hawkeye

Hansa 20. Mai 2006 00:20

Re: Zeilen in einer Datei zählen
 
Was ist mit himitsus Vorschlag ? Würde mich mal interessieren, was die Stringliste interessanter macht. Wenn die Zeilen nicht gleich lang sind, ist das der einfachste Vorschlag zum Ziel zu kommen. Und das ohne Create und Delete und Speicher. 8) Es gibt Error oder eben nicht, zumindest aber kein sich langsam aufbauendes Speicherleck.

himitsu 20. Mai 2006 00:27

Re: Zeilen in einer Datei zählen
 
Zitat:

Zitat von Hansa
Was ist mit himitsus Vorschlag.

meines ist eventuell nicht so schnell (kommt drauf an wieviele Zeilen es gibt und wie groß die Datei ist), aber es gibt garantiert kein Speicherleck und der Speicherverbrauch ist auch total gering (460 Byte bis maximal Zeilenlänge), da ja nicht die ganze Datei im Speicher landet

Hansa 20. Mai 2006 01:02

Re: Zeilen in einer Datei zählen
 
Himitsu, was redest Du da ? Ich meine das :
Zitat:

Zitat von himitsu
..(kommt drauf an wieviele Zeilen es gibt und wie groß die Datei ist)

:shock: Ein Reset weist eigentlich nur dem logischen (Programm)File eine Datei zum öffne zu. Dann werden soviele Bytes gelesen, wie die Zeile tatsächlich lang ist. Natürlich immer wieder bis EOF. Große Datei -> dauert länger, als bei kleiner Datei, weil eben mehr Zeilen. Aber ich mülle mir wegen Fehler nicht den Speicher zu ! Im Fehlerfall wegen vergessener Speicher-Freigabe, die manuell gemacht werden muß, wird das Programm sogar immer langsamer ! Der Effekt dürfte bei 60.000 Zeilen allerdings nicht mal zu bemerken sein bei neuem Rechner, der mit 3.000.000.000 mal taktet pro Sek. und das bei 200.000.000.000 Zeichen als Festplattenspeicher. Man muß die Zahlen echt mal aufschreiben und in Bezug setzen zu 60.000 Zeilen mit < 1000 Zeichen ! Da an der Stelle was an Zeit sparen zu wollen, das ist ähnlicher Unfug, wie wegen 300 kB mit nonVCL anzufangen. Sorry, Luckie. :mrgreen:

himitsu 20. Mai 2006 02:44

Re: Zeilen in einer Datei zählen
 
Also, selbst wenn bei TextFile ein Fehler auftreten sollte dann ist wäre das Speicherleck jedenfalls geringer, als wenn was bei der StringList passiert (nach den obrigen Codes)

Aber man kann ja auch nochmehr an Code einsparren und die ganzen I/O-Checks weglassen
Delphi-Quellcode:
Var F: TextFile;
  Count: Integer;

Count := 0;
AssignFile(F, ...);
FileMode := fmOpenRead;
{$I-}
Reset(F);
While not EoF(F) do Begin
  ReadLn(F);
  Inc(Count);
End;
CloseFile(F);
{$I+}
If IOResult <> 0 Then Count := -1;

// Count >= 0     Count = Zeilenanzahl
// Count = -1     Fehler

Aber hast du dir mal angesehn, was TStringList.LoadFromFile macht?
Das erstellt erstmal 'nen FileStream
kopiert den Inhalt der Datei in einen String
zerlegt den großen String in kleine Strings
und fügt diese kleinen Strings in die StringListe ein ... und zwar jeden einzeln (was intern auch wieder einiges an rumcopieren verursacht)
und gibt zum schluß wieder die beiden Strings und den FileStream frei (man hat also zeitweise über das Doppelte der Dateigröße im RAM und wenn die Datei aus nur einem String besteht sogar as Dreifache
...
tja und zum Schluß muß auch alles wieder freigegeben werden

turboPASCAL 20. Mai 2006 04:59

Re: Zeilen in einer Datei zählen
 
Da stimme ich zu, was noch geht ist einen Grösseren Block zu lesen um die Geschwindigkeit zu erhöhen (Blockread).

Sharky 20. Mai 2006 07:10

Re: Zeilen in einer Datei zählen
 
Und hier mal eine kleine Anregung von mir *g*
Delphi-Quellcode:
function CountLines(const aFileName: string): Integer;
var
  DateiStream: TFileStream;
  CurrentByte: Word;
  Zeilen: Integer;
const
  LineBreak = 10;
begin
  result := -1;
  if (FileExists(aFileName)) then
  begin
    DateiStream := TFileStream.Create(aFileName, fmOpenRead);
    try
      zeilen := 0;
      if (DateiStream.Size > 0) then
      begin
        zeilen := 1;
        DateiStream.Position := 0;
        while DateiStream.Position < DateiStream.Size do
        begin
          DateiStream.Read(CurrentByte, 1);
          if (CurrentByte = LineBreak) then
          begin
            Inc(Zeilen);
          end;
        end;
      end;
    finally
      DateiStream.Free;
    end;
    result := Zeilen;
  end;
end;

procedure TDemoForm.btn_testClick(Sender: TObject);
var
  Zeilen: Integer;
begin
  Zeilen := CountLines('c:\test.txt');
  ShowMessageFmt('%d', [Zeilen]);
end;

happyaura 20. Mai 2006 14:31

Re: Zeilen in einer Datei zählen
 
Hallo, da bin ich wieder.

Erst einmal auf die frage, warum ich mich für TStrinGrid entschieden hab. Hab den datentyp noch nicht benutzt und einfach mal ausprobieren wollen. Vielen Dank für den Hinweis mit .Destroy und .Free, hatte mir die hilfe nicht angeschaut und dacht mir .destroy könnt das tun, was ich will und das tat es dann auch (irgendwie ;-) ). Außerdem

Es handelt sich nicht um große Dateien, sind kleiner als 1 MB, in sofern hab ich zeitlich keinen unterschied zu der methode von himitsu gesehen.
Aber vielleicht ist es ein wenig mit Spatzen auf Kanonen schießen (oder so ähnlich ;-) ), um so ein kleine süße Integer zu bekommen.
Nun bleibt nur noch die frage: TextFile oder FileStream, sprich Code von himitsu oder Sharky.

Vielen dank erst einmal für eure ausführlichen Erläuterungen.

Gruß Martin

P.S. Kann mir vielleicht noch jeman sagen, wie man in einer Combobox es hinbekommt, dass man dort keine Eingaben tätigen kann, sondern nur aus den vorgegebenen werten wählen kann? Ich konnte die entsprechende Einstellung leider nicht finden. Eigentlich gehört das nicht zu diesem Topic, lohnt aber kaum, ein neues Topic aufzumachen, oder?

Hawkeye219 20. Mai 2006 14:35

Re: Zeilen in einer Datei zählen
 
Zitat:

Zitat von happyaura
P.S. Kann mir vielleicht noch jeman sagen, wie man in einer Combobox es hinbekommt, dass man dort keine Eingaben tätigen kann, sondern nur aus den vorgegebenen werten wählen kann? Ich konnte die entsprechende Einstellung leider nicht finden. Eigentlich gehört das nicht zu diesem Topic, lohnt aber kaum, ein neues Topic aufzumachen, oder?

Ok, ich sage es dir auch ganz leise: TComboBox.Style = csDropDownList :wink:

Gruß Hawkeye

happyaura 20. Mai 2006 15:35

Re: Zeilen in einer Datei zählen
 
ah, vielen dank. dann ist es nicht verwunderlich, dass ich es nicht gefunden hab, war primär auf der suche nach einem boolwert, den ich auf true oder false setzen muß...

Hansa 20. Mai 2006 16:29

Re: Zeilen in einer Datei zählen
 
Zitat:

Zitat von happyaura
...Nun bleibt nur noch die frage: TextFile oder FileStream, sprich Code von himitsu oder Sharky.

Ist das denn immer noch nicht klar ? :shock: Bei himitsus Variante muß nicht extra Speicher alloziert werden. Insofern braucht man sich auch nicht um die Freigabe kümmern. Lediglich eine Variable als Puffer für readln (t,st); Stop ! Nicht mal die braucht man. readln (t); reicht zum zählen. Das ist sehr kurz zu machen. Sharkys Variante hat auch einen Vorteil : es erscheint kein .NET-Hinweis von wegen "File of : unsicherer Typ". Deshalb ist es gut, daß auch die Stream Variante hier drin steht. Falls einer seine Textdateien rausschmeißen will und nicht weiß wie das anders geht.

Aber noch ein Effekt am Rande, weil die Geschwindigkeit erwähnt wurde. Mußte auch mal zigtausend Zeilen einlesen und in DB schreiben. Der Code sah ungefähr so aus :

Delphi-Quellcode:
readln (t,st);
Memo1.Lines.Add (st);
// in DB wegschreiben
Überlegung war folgende : was in die DB muß, das könnte man ja zumindest teilweise anzeigen, um zu sehen wie weit das Programm ist. Je nach Dateigröße lief das so ca. 5 Min. Was jetzt kommt ist kein Witz ! Das wollte keiner glauben, inkl. mir ! Das Programm lief plötzlich viel schneller. Allerhöchstens noch 2 Min. Gut, völlig unmöglich : DB gelöscht. Laufen lassen : die Daten waren da, wie vorher auch schon. Dateidatum von DB überprüft. Tja, die Zeit stimmte. Neuer DB-Cache irgendwie aktiviert, oder was gibts noch was es nicht geben sollte ?? Also Sicherung vom Vortag überspielt : 5 Min. Dann habe ich den Source verglichen. Zeile für Zeile, ob da event. eine größere Gruppe von DB-Feldern aus Versehen weg war. Nichts ! Bis auf diese Stelle war der Source identisch :

Delphi-Quellcode:
readln (t,st);
//Memo1.Lines.Add (st);
// in DB wegschreiben
Lediglich das Memo war auskommentiert, aber das war ja wohl ziemlich egal. Denkste ! Die Anzeige mit dem Memo war alleine für den Effekt verantwortlich ! Sonst nichts. :wall: Das ist auch eindeutig reproduzierbar. Ich glaube nicht, daß irgendwer zwischen readln oder Stream einen Effekt beobachtn kann, der nur irgendwie in die Nähe solcher Zeitunterschiede kommt.


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