Конференция "Начинающим" » Сколько строк в файле? [D7, XP]
 
  • operator © (28.03.08 16:43) [0]
    Как быстрее всего узнать сколько строк в текствово файле?
  • Сергей М. © (28.03.08 16:50) [1]
    Быстрее всего будет подсчитать кол-во вхождений символов разделителей (или последовательностей символов-разделителей) строк.
  • Palladin © (28.03.08 16:51) [2]
    Причем правильно прочитать :) а не бредить в исходниках...
  • operator © (28.03.08 17:45) [3]
    var r:textfile; s:string;
    begin
    assignfile(r,filename);
    reset(r);
    al:=0;
    while not eof(r) do begin
      inc(al);
      readln(r,s);
    end;
    closefile(r);



    вот такая мутатень не радует...

    а вообще через что следует реализовывать? то есть в сторону чего думать )
  • Palladin © (28.03.08 17:50) [4]
    это правильная мутотень, ты не сможешь узнать сколько карт из 10 черного цвета не перебрав их все...
  • operator © (28.03.08 17:57) [5]
    просто как-то медленно работает... думал может есть средство какое-нибудь готовое)
  • Palladin © (28.03.08 17:58) [6]
    ну вот теперь есть, ты ж его написал, вот оно теперь и готовое
  • clickmaker © (28.03.08 17:59) [7]

    > а вообще через что следует реализовывать? то есть в сторону
    > чего думать

    CreateFile - CreateFileMapping - MapViewOfFile
    подсчет в буфере символов #13 или #10
    UnmapViewOfFile - CloseHandle - CloseHandle
  • Palladin © (28.03.08 18:01) [8]

    > clickmaker ©   (28.03.08 17:59) [7]

    выигрыш копейки будет скорее всего... и сложнее все гораздо чем просто подсчет символов #13 или #10, бо они в паре идут... хотя ща попробую наваять и потестировать...
  • Плохиш © (28.03.08 18:04) [9]

    >   readln(r,s);

    readln(r);

  • Palladin © (28.03.08 18:42) [10]
    чет нифика не пойму я на этих тестах

    Function GetLinesCountMMF(Const p_strFileName:String):Cardinal;
    Const
    BUF_SIZE=32*1024*1024;

    Type
    TFileMapRec=Record
    _File:HFILE;
    _Map:THandle;
    _Size:Int64;
    End;

    Function OpenFile(Const p_strFileName:String):TFileMapRec;
    Var
    slo,shi:Cardinal;
    Begin
    Result._File:=CreateFile(PChar(p_strFileName), GENERIC_READ,FILE_SHARE_READ,Nil,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
    slo:=Windows.GetFileSize(Result._File,@shi);
    Int64Rec(Result._Size).Lo:=slo;
    Int64Rec(Result._Size).Hi:=shi;
    Result._Map:=CreateFileMapping(Result._File,Nil,PAGE_READONLY,0,0,Nil);
    End;

    Procedure CloseFile(Var rp_rFile:TFileMapRec);
    Begin
    CloseHandle(rp_rFile._Map);
    CloseHandle(rp_rFile._File);
    End;

    Function MapBuff(p_rFile:TFileMapRec;p_nFrom:Int64;p_nCount:Cardinal):Pointer;
    Begin
    Result:=MapViewOfFile(p_rFile._Map, FILE_MAP_READ,Int64Rec(p_nFrom).Hi,Int64Rec(p_nFrom).Lo,p_nCount);
    End;

    Procedure UnMapBuff(Var p:Pointer);
    Begin
    UnmapViewOfFile(p);
    End;

    Var
    _File:TFileMapRec;
    Buf:PByteArray;
    p:Int64;
    LastBufByteIsCR:Boolean;

    Function _Count(p_nFrom:Int64;p_nCount:Cardinal):Cardinal;
    Var
    StartFrom:Integer;
    i:Integer;
    Begin
    Buf:=MapBuff(_File,p_nFrom,p_nCount);
    Try
     Result:=0;
     If Not LastBufByteIsCR Then StartFrom:=0 Else
      If Buf[0]<>10 Then StartFrom:=0 Else
       Begin
        Inc(Result);
        StartFrom:=1;
       End;
     For i:=StartFrom to p_nCount-2 Do
      If (Buf[i]=13) and (Buf[i+1]=10) Then Inc(Result);
     LastBufByteIsCR:=Buf[p_nCount-1]=13;
    Finally
     UnMapBuff(Pointer(Buf));
    End;
    End;

    Begin
    _File:=OpenFile(p_strFileName);
    Try
     p:=0;
     Result:=0;
     While True Do
      If (p+BUF_SIZE)>_File._Size Then
       Begin
        Result:=Result+_Count(p,_File._Size-p);
        Break;
       End Else
       Begin
        Result:=Result+_Count(p,BUF_SIZE);
        Inc(p,BUF_SIZE);
       End;
    Finally
     CloseFile(_File);
    End;
    End;

    Function GetLinesCountRLN(Const p_strFileName:String):Cardinal;
    Var
    f:TextFile;
    Begin
    Result:=0;
    AssignFile(f,p_strFileName);Reset(f);
    While Not Eof(f) Do
     Begin
      Inc(Result);
      Readln(f);
     End;
    CloseFile(f);
    End;

    Function vtRandomStr(p_nMaxLen:Integer=300):String;
    Var
    i:Integer;
    Begin
    SetLength(Result,Random(p_nMaxLen));
    For i:=1 to Length(Result) Do
     Result[i]:=Char(Random(223)+32);
    End;

    procedure TForm1.CreateRndTxtFile;
    Var
    i:Integer;
    f:TextFile;
    begin
    AssignFile(f,'c:\bigtext.txt'); Rewrite(f);
    For i:=0 to 2000000-1 Do WriteLn(f,vtRandomStr(400));
    CloseFile(f);
    end;

    procedure TForm1.Bench;
    Var
    gtc:Cardinal;
    tc:Cardinal;
    i:Integer;

    Procedure _Tick1;
    Begin
     tc:=GetTickCount;
     Memo1.Lines.Add('RLN:'+IntToStr(GetLinesCountRLN('c:\bigtext.txt'))+':'+IntToStr(GetTickCount-tc));
     Application.ProcessMessages;
    End;

    Procedure _Tick2;
    Begin
     tc:=GetTickCount;
     Memo1.Lines.Add('MMF:'+IntToStr(GetLinesCountMMF('c:\bigtext.txt'))+':'+IntToStr(GetTickCount-tc));
     Application.ProcessMessages;
    End;

    begin
    gtc:=GetTickCount;
    For i:=0 to 5 Do _Tick1;
    Memo1.Lines.Add(IntToStr((GetTickCount-gtc) div 6));
    Application.ProcessMessages;
    gtc:=GetTickCount;
    For i:=0 to 5 Do _Tick2;
    Memo1.Lines.Add(IntToStr((GetTickCount-gtc) div 6));
    Application.ProcessMessages;
    end;



    на объемах мегабайт в 400-500, MMF выигрывает по скорости в 5 раз, на объеме в 1.9Гб (10 млн строк я создал файл), выигрыш копеечный...

    видимо очень сильно влияет внутренний буффер IO системы и наличие памяти...

    WinXP, SP2, 1.5Гб ОЗУ
  • Плохиш © (28.03.08 18:56) [11]

    > AssignFile(f,p_strFileName);Reset(f);

    А если между ними ещё и SetTextBuf поставить?
  • operator © (28.03.08 18:57) [12]
    Спасибо , пойду юзать....
  • Palladin © (28.03.08 19:06) [13]

    > Плохиш ©   (28.03.08 18:56) [11]

    результат конечно на рыльце, но до MMF недотягивает

    RLN:2000000:6391
    RLN:2000000:6359
    RLN:2000000:6344
    RLN:2000000:6359
    RLN:2000000:6344
    RLN:2000000:6359
    6359
    MMF:2000000:1032
    MMF:2000000:1046
    MMF:2000000:1032
    MMF:2000000:1047
    MMF:2000000:1031
    MMF:2000000:1047
    1039
    RLN32:2000000:3750
    RLN32:2000000:3750
    RLN32:2000000:3781
    RLN32:2000000:3734
    RLN32:2000000:3719
    RLN32:2000000:3781
    3752



    претендент

    Function GetLinesCountRLNB32(Const p_strFileName:String):Cardinal;
    Var
    f:TextFile;
    Buf:Pointer;
    Begin
    GetMem(Buf,32*1024*1024);
    Result:=0;
    AssignFile(f,p_strFileName);SetTextBuf(f,Buf^,32*1024*1024);Reset(f);
    While Not Eof(f) Do
     Begin
      Inc(Result);
      Readln(f);
     End;
    CloseFile(f);
    FreeMem(Buf);
    End;



    про добавления в Bench рассказывать не буду, и так понятно :)

    файл:
    2 000 000 строк
    размер - 403 373 064b
  • Zeqfreed © (28.03.08 19:22) [14]
    $ cat ~artem/downloads/slackware-12.0-install-d1.iso | hexdump > /tmp/bigfile
    $ ls -lh /tmp/bigfile
    -rw-r--r-- 1 artem artem 1.9G 2008-03-28 21:27 /tmp/bigfile
    $ time { cat /tmp/bigfile | wc -l ; }
    41430184

    real    0m27.440s
    user    0m1.474s
    sys     0m3.161s

    Это достаточно длинно? :)
  • Palladin © (28.03.08 19:24) [15]
    а не прекращает ли cat работу при встрече #26, ась? :)
  • Zeqfreed © (28.03.08 19:27) [16]
    > Palladin ©   (28.03.08 19:24) [15]

    А должно? Я что сделал. Я сделал шестнадцатиричный дамп образа диска слаки и посчитал в нем строчки. Как видно, было найдено 41430184 строки, т.е. вполне достаточно :)
  • Palladin © (28.03.08 19:28) [17]
    ну фиг знает... по хорошему вроде как дОлжно... #26 это ж конец файла... :)
  • Игорь Шевченко © (28.03.08 19:35) [18]

    > выигрыш копейки будет скорее всего...


    кстати точно копейки, подтверждаю.
  • Игорь Шевченко © (28.03.08 19:39) [19]
    Как узнать количество строк в текстовом файле - загрузить его в Memo и посчитать Memo1.Lines.Count
  • Германн © (28.03.08 21:23) [20]

    > Игорь Шевченко ©   (28.03.08 19:39) [19]

    Дык ведь действительно попробует загрузить в Memo!
  • Игорь Шевченко © (28.03.08 21:29) [21]
    Германн ©   (28.03.08 21:23) [20]

    У нас пробуют. Правда получают по рукам, вплоть до увольнения, но бывает.
  • MetalFan © (28.03.08 21:39) [22]

    > Игорь Шевченко ©   (28.03.08 21:29) [21]

    эдакие вы садисты!
  • Джо © (28.03.08 21:54) [23]
    Господь с вами, что за ужасы. Впрочем, вполне похоже на правду.
  • tesseract © (28.03.08 22:08) [24]

    > У нас пробуют. Правда получают по рукам, вплоть до увольнения,
    >  но бывает


    Ужас, как таких на работу вообще берут ?
  • Leonid Troyanovsky © (28.03.08 22:43) [25]

    > Palladin ©   (28.03.08 18:42) [10]

    > чет нифика не пойму я на этих тестах

    Все уже проверено до нас.
    Быстрее всего последовательное (FILE_FLAG_SEQUENTIAL_SCAN) чтение
    с оптимальным размером буфера.

    --
    Regards, LVT.
  • Palladin © (29.03.08 00:24) [26]
    тааак... FILE_FLAG_SEQUENTIAL_SCAN то я и забыло... но проверю только заутра :) на WM5 Delphi не работает...

    если кому то захочется пораньше, то вперед, копи паст никто не отменял
  • Loginov Dmitry © (29.03.08 00:37) [27]
    при первом вызове _Tick2 благодаря FILE_FLAG_SEQUENTIAL_SCAN достигается ускорение 13% (файл 1,6 ГБайт, 2ГБ ОЗУ). При втором и последующих вызовах _Tick2 наблюдается значительное падение скорости.
  • Leonid Troyanovsky © (29.03.08 14:35) [28]

    > Palladin ©   (29.03.08 00:24) [26]

    > тааак... FILE_FLAG_SEQUENTIAL_SCAN то я и забыло

    http://groups.google.com/group/fido7.su.win32.prog/msg/e4edc3fb35401f38
    http://groups.google.com/group/fido7.su.win32.prog/msg/c166d6d784f3864c

    --
    Regards, LVT.
 
Конференция "Начинающим" » Сколько строк в файле? [D7, XP]
Есть новые Нет новых   [134433   +22][b:0][p:0.006]