Entwickler-Ecke

Dateizugriff - Zeilenanzahl in txt Datei


der organist - Mo 22.12.08 13:02
Titel: Zeilenanzahl in txt Datei
Hi Leutz,

wie bekomme ich die Zeilenanzahl einer TextFile heraus, ohne sie in iergendeine Komponente zu laden?

Thx, MfG


Moderiert von user profile iconChristian S.: Topic aus Delphi Language (Object-Pascal) / CLX verschoben am Mo 22.12.2008 um 12:04


chrisw - Mo 22.12.08 13:22

Ich würde die Datei laden, zeilenweise lesen, Zähler hochzählen.

ala:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
function ZaehleZeilen(filename: String) : Integer;
var F : TextFile;
    S : String;
begin 
  AssignFile(F,filename);
  Reset(F);
  Result := 0;  
  while not Eof(F) do
  begin
    ReadLn(F,S);
    inc(Result);
  end;
  CloseFile(F);
end;


Delete - Mo 22.12.08 13:31

Oder mit einer TStringlist:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
function ZaehleZeilen(const Filename: String) : Integer; 
var sl: TStringlist;
begin
  if not FileExists(Filename) then
    Result := -1
  else
    begin
      sl := TStringlist.Create;
      try
        sl.LoadFromFile(Filename);
        Result := sl.Count;
      finally
        sl.Free;
      end;
    end;
end;


chrisw - Mo 22.12.08 13:33

Ja, wobei man sich hier streiten kann, ob TStringList eine Komponente ist.


Delete - Mo 22.12.08 13:35

Klasse ja, Komponente nein.


MSCH - Mo 22.12.08 13:50

Via Blockread/Blockwrite - geht am schnellsten und dann nur #10#13 zählen.

TStringList verbraucht Speicher und ist nicht sooo performant.

:-)Msch


Delete - Mo 22.12.08 14:00

Das ist zweifellos richtig, aber dann sollte man auch Fehlerfälle behandeln.


der organist - Mo 22.12.08 17:04

gibts da keine andere Möglichkeit??


der organist - Mo 22.12.08 17:09

erst mal, am einfachsten finde ich die Lösung von chrisw. Danke dafür.
Danke auch an alle anderen, die sich hier die Mühe gegeben haben.


Blackheart666 - Mo 22.12.08 17:50

user profile iconder organist hat folgendes geschrieben Zum zitierten Posting springen:
erst mal, am einfachsten finde ich die Lösung von chrisw. Danke dafür.
Danke auch an alle anderen, die sich hier die Mühe gegeben haben.


Obwohl doch die bessere und wohl auch einfachere Variante die von DeddyH ist.


delphi10 - Mo 22.12.08 18:01

Mal angenommen, man hätte ein konstante Zeilenbreite von 100 Zeichen, dann ginge es auch so:

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
Var
F : File;
const
Zeilenbreite : Integer = 100;
.
.
AssignFile(F,'Name');
Reset(f,Zeilenbreite);
x := FileSize(F);
CloseFile(F);


X gibt die Anzahl der Datensätze in der Datei F an. Durch Reset(f,100), wird ein Datensatz auf 100 Zeichen festgelegt.
Ja, zugegeben. Konstante Zeilenbreite kommt wohl eher selten vor. Aber schnell ist es..!
cu Delphi10


Delete - Mo 22.12.08 18:51

Um das einmal zu komplettieren (speicherschonende Variante mit Fehlerbehandlung):

Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
function ZaehleZeilen(const filename: String) : Integer;
var F : TextFile;
begin
  Result := -1;
  if FileExists(filename) then
    begin
      AssignFile(F,filename);
      {$I-}
      Reset(F);
      {$I+}
      if IOResult = 0 then
        begin   
          Result := 0;  
          while not Eof(F) do
            begin
              ReadLn(F);
              inc(Result);
            end;
          CloseFile(F);
        end;
    end;
end;


der organist - Mo 22.12.08 19:42

user profile iconBlackheart666 hat folgendes geschrieben Zum zitierten Posting springen:
user profile iconder organist hat folgendes geschrieben Zum zitierten Posting springen:
erst mal, am einfachsten finde ich die Lösung von chrisw. Danke dafür.
Danke auch an alle anderen, die sich hier die Mühe gegeben haben.


Obwohl doch die bessere und wohl auch einfachere Variante die von DeddyH ist.


zwischen einfach und schwierig ein großer Unterschied ist, junger Padawan :D Nein, es geht mir um eine einfache Lösung, ohne neue Komponenten oder Typen...


jaenicke - Mo 22.12.08 19:52

user profile iconBlackheart666 hat folgendes geschrieben Zum zitierten Posting springen:
Obwohl doch die bessere und wohl auch einfachere Variante die von DeddyH ist.
Was ist daran besser die komplette Datei erst in den Speicher zu laden, wenn du die dort gar nicht brauchst? :gruebel:


alzaimar - Mo 22.12.08 20:14

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Was ist daran besser die komplette Datei erst in den Speicher zu laden, wenn du die dort gar nicht brauchst? :gruebel:
Wir haben genug Speicher, es tut keinem weh, ist einfach hingetippt, hinreichend stabil (da geprüfter Code verwendet wird) und funktioniert, ohne groß drüber nachzudenken... Wenn das kein Grund ist.

Du kannst ja eine allgemeingültige Klasse zum zählen von Zeilen in beliebig großen Textdateien schreiben. Dann würde ich per TFileStream sehr große Blöcke einlesen und die #13#10 zählen (wurde schon erwähnt). Dabei müssen blockboundaries berücksichtigt werden (#13 am Ende des aktuellen und #10 am Anfang des nächsten Blockes) usw. Das ist aber nicht trivial und ein eindeutiger Overkill.


jaenicke - Mo 22.12.08 20:20

Eine einfache Lösung, die ohne die Speicherverwendung auskommt, wurde ja bereits gepostet. :roll:


alzaimar - Mo 22.12.08 20:25

user profile iconjaenicke hat folgendes geschrieben Zum zitierten Posting springen:
Eine einfache Lösung, die ohne die Speicherverwendung auskommt, wurde ja bereits gepostet. :roll:
Die nicht sonderlich performant ist :roll: :wink:


Delete - Mo 22.12.08 20:25

Wünscht Ihr Euch zu Weihnachten eigentlich Erbsen zum Zählen oder lieber Haare zum Spalten? :mrgreen:


alzaimar - Mo 22.12.08 20:28

Spielverderber :schmoll:


jaenicke - Mo 22.12.08 20:28

Ich nehm die Erbsen :D.


Delete - Mo 22.12.08 20:36

Bitteschön [http://www.wdr.de/radio/wdr2/_m/images/upload/westzeit/erbsen_roh_160x120.jpg] *g*


jaenicke - Mo 22.12.08 21:44

Hmm, lecker die 303 Erbsen. :D


der organist - Di 23.12.08 00:11

momentan sieht meine Lösung so aus, will aber nich richtig funzen :(. Vllt ist auch einfach mein Ansatz falsch. Wichtig ist, dass in der letzten Zeile des Dokumentes "END." steht, damit ich weiss (besser noch, damit das Programm weiss), wann die Datei zu Ende ist:


Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
  while HellFreezes do begin
    ReadLn(input, Line);
    inc(Finish);
    if Line = 'END.' then begin
      Hellfreezes:=false;
    end;
  end;


HellFreezes ist eine Booleanariable, die voher auf True gesetzt wurde, input die Textdatei, ich hab auch schön AssignFile benutzt, naja und Line ist ein String, wer hätte es gedacht.


jaenicke - Di 23.12.08 00:36

Das Programm weiß das auch so.
user profile iconDeddyH hat folgendes geschrieben Zum zitierten Posting springen:

Delphi-Quelltext
1:
while not Eof(F) do                    
Wenn du die Zeile nicht mitzählen willst, dann zieh einfach am Ende 1 ab von der Zahl.


Delete - Di 23.12.08 03:31

Naja, ganz so einfach ist es denn nun doch nicht, der Inhalt der Zeile müsste dann noch geprüft werden. Das könnte dann so aussehen:

Delphi-Quelltext
1:
while not Eof(F) and (AnsiLowerCase(trim(Zeile)) <> 'end.'do                    

Wobei die Zeile dann im Gegensatz zu meinem letzten Beispiel doch wieder in einer Stringvariablen gepuffert werden muss.


jaenicke - Di 23.12.08 04:50

Warum ist es nicht so einfach? Wenn das "end." in der letzten Zeile steht (das sagte er ja), dann muss das doch gar nicht geprüft werden. :nixweiss:
Einfach bis zum Ende der Datei die Zeilen zählen und fertig, dass in der letzten Zeile dann das "end." steht ändert doch nix an der Zeilenanzahl. :nixweiss:


Delete - Di 23.12.08 17:35

Und öffnest Du die Datei, fügst ein oder zwei Zeilenumbrüche hinzu, funktioniert das Ganze anscheinend nicht mehr. Wieso verlasst Ihr Euch eigentlich immer darauf, dass alles schon irgendwie stimmen wird?


jaenicke - Di 23.12.08 17:39

Ich habe Vorbedingungen und Nachbedingungen, und angegeben war die Vorbedingung, dass "end." in der letzten Zeile steht, nicht, dass danach noch Leerzeichen kommen. Also muss ich um die Nachbedingung zu erreichen auch nicht davon ausgehen, dass die Vorbedingung nicht erfüllt war und nach der dann doch nicht letzten Zeile noch leere kommen oder ähnliches.

Wenn die Spezifikation der Datei doch nicht gestimmt hat muss das eben angepasst werden. Aber zunächst habe ich keinen Grund an einer Aussage zu zweifeln. :nixweiss:


Delete - Di 23.12.08 17:47

Ich geb' s auf.