delphi 统计文本文件行数  
官方Delphi 学习QQ群: 682628230(三千人)\n
频道

delphi 统计文本文件行数


这么个简单问题,居然在网上找不到现成的代码。只好自己做了。


1、TStringList 法:


function GetTextLineCount_SL(const strFileName: string): UInt64;

begin

  with TStringList.Create do

  begin

    LoadFromFile(strFileName);

    Result := Count;

    Free;

  end;

end;

这种方案,只能针对小文件,大文件就不行了。

既然是文本文件,那么可以使用 readln 方法来读取试试。


2、TextFile 法:


function GetTextLineCount_TF(const strFileName: string): UInt64;

var

  F: TextFile;

begin

  Result := 0;

  AssignFile(F, strFileName);

  SetTextBuf(F, Buffer);

  Reset(F);

  while not eof(F) do

  begin

    Readln(F);

    Inc(Result);

  end;

  CloseFile(F);

end;

这种方案。有个缺陷:它返回的行数和 TStringlist 法返回的行数是不一样的。

原因:TStringlist 法,#13#10 当成换行,#13、#10也会被当成换行进行计数(具体可以参看 Delphi 源码)。而 readln 则不会。

看来针对大文件,还得另想它法。

试试文件流的方式。


3、FileStream 法(Linux 下,只用 #10 作为换行符,而 Windows 下,#13#10、#13、#10,都可作为换行符):


function GetTextLineCount_FS(const strFileName: string; const bLinux: Boolean = False): UInt64;

var

  FS      : TFileStream;

  I, Count: Integer;

  startPos: Integer;

  partXPos: Integer;

begin

  Result   := 0;

  startPos := 0;

  partXPos := 0;

  FS       := TFileStream.Create(strFileName, fmOpenRead);

  try

    Count := FS.Size;

    if bLinux then

    begin

      while FS.Position < Count do

      begin

        FS.Read(Buffer[0], c_intLength);

        startPos := startPos + c_intLength;

        if startPos > Count then

          partXPos := startPos - Count;

 

        for I := 0 to c_intLength - 1 - partXPos do

        begin

          if (Buffer[I] = #10) then

            Inc(Result);

        end;

      end;

    end

    else

    begin

      while FS.Position < Count do

      begin

        FS.Read(Buffer[0], c_intLength);

        startPos := startPos + c_intLength;

        if startPos > Count then

          partXPos := startPos - Count;

 

        for I := 0 to c_intLength - 1 - partXPos do

        begin

          if (Buffer[I] = #13) and (Buffer[I + 1] = #10) then

            Inc(Result)

          else if (Buffer[I] = #13) and (Buffer[I + 1] <> #10) then

            Inc(Result)

          else if (Buffer[I] <> #13) and (Buffer[I + 1] = #10) then

            Inc(Result);

        end;

      end;

    end;

  finally

    FS.Free;

  end;

end;

测试:(函数名、文件数、耗时)

30M  文本文件:

  GetTextLineCount_SL  828125   987毫秒

  GetTextLineCount_TF  828092   484毫秒

  GetTextLineCount_FS  828125     96毫秒


600M 文本文件:

  GetTextLineCount_SL   <         不支持        >

  GetTextLineCount_TF  14177571   8758毫秒

  GetTextLineCount_FS  14181548   1659毫秒(Linux 829毫秒)



第三种方案最好,即兼容第一种,又比第一种效率高出 10 倍左右。


源码:GitHub - dbyoung720/TextLineCount: Text Line Count

————————————————


原文链接:https://blog.csdn.net/dbyoung/article/details/121681353



推荐分享
图文皆来源于网络,内容仅做公益性分享,版权归原作者所有,如有侵权请告知删除!
 

Copyright © 2014 DelphiW.com 开发 源码 文档 技巧 All Rights Reserved
晋ICP备14006235号-8 晋公网安备 14108102000087号

执行时间: 0.78438591957092 seconds