Articles   Members Online:
-Article/Tip Search
-News Group Search over 21 Million news group articles.
-Delphi/Pascal
-CBuilder/C++
-C#Builder/C#
-JBuilder/Java
-Kylix
Member Area
-Home
-Account Center
-Top 10 NEW!!
-Submit Article/Tip
-Forums Upgraded!!
-My Articles
-Edit Information
-Login/Logout
-Become a Member
-Why sign up!
-Newsletter
-Chat Online!
-Indexes NEW!!
Employment
-Build your resume
-Find a job
-Post a job
-Resume Search
Contacts
-Contacts
-Feedbacks
-Link to us
-Privacy/Disclaimer
Embarcadero
Visit Embarcadero
Embarcadero Community
JEDI
Links
How to count the lines of text contained in a text file Turn on/off line numbers in source code. Switch to Orginial background IDE or DSP color Comment or reply to this aritlce/tip for discussion. Bookmark this article to my favorite article(s). Print this article
20-Mar-03
Category
Files Operation
Language
Delphi 2.x
Views
160
User Rating
No Votes
# Votes
0
Replies
0
Publisher:
DSP, Administrator
Reference URL:
DKB
			Author: Jonas Bilinkevicius

How to count the lines of text contained in a text file

Answer:

Solve 1:

The fastest way would be to count the instances of #13#10 yourself. However you 
need to be careful because #13 and #10 could easily be swapped to give #10#13 
instead which makes this kind of counting more difficult. In this case it's far 
easier just to count the instances of one of them and this has the bonus of being 
more compatible with non-Windows (ie. non CR/LF'd) files - not all operating 
systems bother with both #13 and #10. The following is a basic implementation of 
the code:
1   
2   function CountLines(const FileName: string): integer;
3   const
4     BufferSize = 1024;
5     SearchByte = 10;
6   var
7     FileHandle, BytesRead, Index: integer;
8     Buffer: array[1..BufferSize] of byte;
9   begin
10    FileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyWrite);
11    BytesRead := FileRead(FileHandle, Buffer[1], BufferSize);
12    if (BytesRead > 0) then
13      Result := 1
14    else
15      Result := 0;
16    repeat
17      for Index := 1 to Min(BufferSize, BytesRead) do
18      begin
19        if (Buffer[Index] = SearchByte) then
20          Inc(Result);
21      end;
22      BytesRead := FileRead(FileHandle, Buffer[1], BufferSize);
23    until
24      BytesRead <= 0;
25    FileClose(FileHandle);
26  end;


This code is searching for #10's in the file, and treating this as a line 
delimeter. It takes care of the case where an empty file has 0 lines but a file 
with no #10s has one line in the initialisation of the Result return value. You can 
easily modify the seach byte and/or the buffer size.


Solve 2:

If it is a smaller file (< 1 MB) load it into a TStringlist and look at the 
stringlists Count property. If it is larger you need to read it completely and 
count lines. A simple loop would be this:
27  
28  function CountLines(const filename: string): Integer;
29  var
30    buffer: array[0..4095] of Char;
31    f: Textfile;
32  begin
33    Result := 0;
34    Assignfile(f, filename);
35    Reset(f);
36    try
37      SetTextBuffer(f, buffer, sizeof(buffer));
38      while not Eof(f) do
39      begin
40        readLn(f);
41        Inc(result);
42      end;
43    finally
44      Closefile(f);
45    end;
46  end;


Using a larger than the default buffer of 128 bytes speeds the reading somewhat.


Solve 3:

Buffering can help quit a bit:
47  
48  function TextLineCount_BufferedStream(const Filename: TFileName): Integer;
49  const
50    MAX_BUFFER = 1024 * 1024;
51  var
52    oStream: TFileStream;
53    sBuffer: string;
54    iBufferSize: Integer;
55    iSeek: Integer;
56    bCarry: Boolean;
57  begin
58    Result := 0;
59    bCarry := False;
60    oStream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
61    try
62      SetLength(sBuffer, MAX_BUFFER);
63      repeat
64        iBufferSize := oStream.read(sBuffer[1], MAX_BUFFER);
65        if iBufferSize <= 0 then
66          break;
67        {Skip LFs that follow a CR - even if it falls in seperate buffers}
68        iSeek := 1;
69        if bCarry and (sBuffer[1] = #10) then
70          Inc(iSeek);
71        while iSeek <= iBufferSize do
72        begin
73          case sBuffer[iSeek] of
74            #10:
75              Inc(Result);
76            #13:
77              if iSeek = iBufferSize then
78                Inc(Result)
79              else if sBuffer[iSeek + 1] <> #10 then
80                Inc(Result)
81              else
82              begin
83                Inc(Result);
84                Inc(iSeek);
85              end;
86          end;
87          Inc(iSeek);
88        end;
89        {Set carry flag for next pass}
90        bCarry := (sBuffer[iBufferSize] = #13);
91      until
92        iBufferSize < MAX_BUFFER;
93    finally
94      FreeAndNil(oStream);
95    end;
96  end;


			
Vote: How useful do you find this Article/Tip?
Bad Excellent
1 2 3 4 5 6 7 8 9 10

 

Advertisement
Share this page
Advertisement
Download from Google

Copyright © Mendozi Enterprises LLC