-
Как быстрее всего узнать сколько строк в текствово файле?
-
Быстрее всего будет подсчитать кол-во вхождений символов разделителей (или последовательностей символов-разделителей) строк.
-
Причем правильно прочитать :) а не бредить в исходниках...
-
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); вот такая мутатень не радует... а вообще через что следует реализовывать? то есть в сторону чего думать )
-
это правильная мутотень, ты не сможешь узнать сколько карт из 10 черного цвета не перебрав их все...
-
просто как-то медленно работает... думал может есть средство какое-нибудь готовое)
-
ну вот теперь есть, ты ж его написал, вот оно теперь и готовое
-
> а вообще через что следует реализовывать? то есть в сторону > чего думать
CreateFile - CreateFileMapping - MapViewOfFile подсчет в буфере символов #13 или #10 UnmapViewOfFile - CloseHandle - CloseHandle
-
> clickmaker © (28.03.08 17:59) [7]
выигрыш копейки будет скорее всего... и сложнее все гораздо чем просто подсчет символов #13 или #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Гб ОЗУ
-
> AssignFile(f,p_strFileName);Reset(f);
А если между ними ещё и SetTextBuf поставить?
-
Спасибо , пойду юзать....
-
> Плохиш © (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
-
$ 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
Это достаточно длинно? :)
-
а не прекращает ли cat работу при встрече #26, ась? :)
-
> Palladin © (28.03.08 19:24) [15]
А должно? Я что сделал. Я сделал шестнадцатиричный дамп образа диска слаки и посчитал в нем строчки. Как видно, было найдено 41430184 строки, т.е. вполне достаточно :)
-
ну фиг знает... по хорошему вроде как дОлжно... #26 это ж конец файла... :)
-
> выигрыш копейки будет скорее всего...
кстати точно копейки, подтверждаю.
-
Как узнать количество строк в текстовом файле - загрузить его в Memo и посчитать Memo1.Lines.Count
-
> Игорь Шевченко © (28.03.08 19:39) [19]
Дык ведь действительно попробует загрузить в Memo!
-
Германн © (28.03.08 21:23) [20]
У нас пробуют. Правда получают по рукам, вплоть до увольнения, но бывает.
-
> Игорь Шевченко © (28.03.08 21:29) [21]
эдакие вы садисты!
-
Господь с вами, что за ужасы. Впрочем, вполне похоже на правду.
-
> У нас пробуют. Правда получают по рукам, вплоть до увольнения, > но бывает
Ужас, как таких на работу вообще берут ?
-
> Palladin © (28.03.08 18:42) [10]
> чет нифика не пойму я на этих тестах
Все уже проверено до нас. Быстрее всего последовательное (FILE_FLAG_SEQUENTIAL_SCAN) чтение с оптимальным размером буфера.
-- Regards, LVT.
-
тааак... FILE_FLAG_SEQUENTIAL_SCAN то я и забыло... но проверю только заутра :) на WM5 Delphi не работает...
если кому то захочется пораньше, то вперед, копи паст никто не отменял
-
при первом вызове _Tick2 благодаря FILE_FLAG_SEQUENTIAL_SCAN достигается ускорение 13% (файл 1,6 ГБайт, 2ГБ ОЗУ). При втором и последующих вызовах _Tick2 наблюдается значительное падение скорости.
-
|