31. maj 2005 - 15:48Der er
17 kommentarer og 1 løsning
Søge efter tekst i store filer
Jeg vil gerne lave et værktøj til at analysere logfiler med, som er rene tekstfiler 10 mb store.
Værktøjet skal kunne gennemsøge alle filer i et directory og finde alle forkomster af søgeordet fra alle filer. Når søgeordet er fundet skal linjen hvor det forekommer kopieres og vises i f.eks en memo felt.
Mime spm: 1) Hvordan søger man mest effektivt i tekstfiler ?
2) Er det en fordel at kopiere filen ind i f.eks. en stringlist, stringgrid eller lignende ?
3) Hvordan får jeg kopieret den fundne linje over i memofelt ? 4) Er der nogen der har prøvet noget ligende og evt har et eksempel på dette ?
Dette er vel den simple måde men det er nok ikke den hurtigeste, på min langsomme maskine (1.2 Ghz AMD pipfugl) tager det ca. 1 sekund at indlæse en 11 MB textfil og søge gennem den. Hvis opdateringen af button1 aktiveres tager det BETYDELIG længere tid.
Smid en Memo1 på en form.
procedure TForm1.FindTekst(Tekst : string); var StringList : TStringList; i : integer; begin StringList:=TStringList.Create; StringList.LoadFromFile('c:\hk\manual.txt'); // en 11MB fil for i:=0 to StringList.Count-1 do begin if Pos(Tekst,StringList[i])>0 then Memo1.Lines.Add(StringList[i]); // Button1.Caption:=IntTostr(i); // Button1.Update; end;
Som sagt vil jeg gerne lave et værktøj til at analysere log filer med, så det skal kunne søge igennem flere filer og sortere resultatet efter f.eks. tidsstempel.
Vil brug af stringlist og en memo stadig være det bedste valg ?? Kunne det tænkes at der skal bruges threads for at optimere søgningen ??
Jeg skal ikke kunne sige om stringlist og memo er det bedste valg, jeg tror det ikke men det er det eneste jeg lige kan komme på. Hvis de fundne data skal præsenteres for brugeren så er en ListView måske bedre, hvis de ikke skal præsenteres for brugeren så er der ingen grund til at bruge en memo eller ListView så ville jeg bruge en StringList til også at gemme resultatet i. Mht. thread så tror jeg ikke at du vil få noget ud af at bruge flere threads, en enkelt ville nok være en god ide for at undgå at hoved formen dør mens der søges. Nu ser jeg lige at du skriver " sortere resultatet efter f.eks. tidsstempel. " så ville jeg nok bruge en ListView hvis brugeren skal se resultatet eller en StringList hvis ikke.
Hvis man skal bruge en listview til at vise resultat og filen læses ind i en strinlist først, hvordan får jeg så de enkelte dele fra stringlisten ind i de respektive kolonner i listviewen ???
en linie fra loggen ser f.eks. sådan ud: 21:32:11.593,D,PC:2032,server.cpp:1222, ID=27621098 Destination=16 operation=1
Den består af disse 5 dele adskilt med komma: <tidsstempel>,<kategori>,<thread>,<filenavn:linje>,<log tekst>
Har du nogen ide om hvordan jeg kunne få dette lagt ind i 5 kolonner i listviewen ??
Hvis din ListView hedder ListView1 og har 5 kolonner:
procedure TForm1.FindTekst(Tekst : string); var StringList,LinieList : TStringList; i : integer;
procedure SendToListView; var i : integer; begin LinieList.Clear; ExtractStrings([','],[],PChar(StringList[i]),LinieList); if LinieList.Count=5 then begin with ListView1.Items.Add do begin Caption:=LinieList[0]; for i:=1 to 4 do SubItems.Add(LinieList[i]); end; end else showmessage('FEJL: Der er ikke 5 kolonner') end;
begin LinieList:=TStringList.Create; StringList:=TStringList.Create; StringList.LoadFromFile('c:\hk\manual.txt'); // en 11MB fil for i:=0 to StringList.Count-1 do begin if Pos(Tekst,StringList[i])>0 then SendToListView; end;
StringList.Free; LinieList.Free; end;
ok, jeg skal til at læse hvad du skriver inden jeg går igang, jeg kan se at du gerne ville have resultatet ind i en stringlist først, er det nødvedigt for så kan jeg lige rette den til?
Jeg har også fundet ud af at der er flere af mine logfiler hvor der forekommer ',' tegn i selve log teksten og det gør at funktionen 'ExtractStrings' finder flere forekomster i stringlisten end 5. (LinieList.Count > 5)
Kender du en anden metode til at gennemsøge sådan en stringlist, så jeg kun bruger de første 4 fundne og de resterende samles i den 5 LinieList[5] ??
Hvis du skifter SendToListView ud med denne burde det virke, hvis din log tekst ikke altid starter med ID= så vil det ikke virke, så skriv igen.
procedure SendToListView; var x : integer; begin LinieList.Clear; ExtractStrings([','],[],PChar(StringList[i]),LinieList); if LinieList.Count>4 then begin with ListView1.Items.Add do begin Caption:=LinieList[0]; for x:=1 to 3 do SubItems.Add(LinieList[x]); SubItems.Add(copy(StringList[i],Pos('ID=',StringList[i]),MaxInt)); end; end else showmessage('FEJL: Der er mindre end 5 kolonner') end;
Du kunne også bare gøre sådan, så er det ligemeget om din log tekst starter med ID=
procedure SendToListView; var x : integer; begin LinieList.Clear; ExtractStrings([','],[],PChar(StringList[i]),LinieList); if LinieList.Count>4 then begin with ListView1.Items.Add do begin Caption:=LinieList[0]; for x:=1 to 4 do SubItems.Add(LinieList[x]); for x:=5 to LinieList.Count-1 do SubItems[3]:=SubItems[3]+','+LinieList[x]; end; end else showmessage('FEJL: Der er mindre end 5 kolonner') end;
nej logteksten starter ikke med noget bestemt, men kan være hvad som helst, derfor var der også også pludselig nogen med komma-tegn i teksten. Det skyldes at loggen bruges af mange forskellige applikationer på samme tid.
Hvis de 4 første dele i dine log linier altid har samme længde kunne man også benytte nogle copy(a,b) i stedet for ExtractStrings, det ville nok være hurtigere men hvis det kun drejer sig om nogle få linier der findes ved søgninger så er det self. ligemeget.
Jeg tænkte på at hvis: 21:32:11.593,D,PC:2032,server.cpp:1222, ID=27621098 Destination=16 operation=1 <tidsstempel>,<kategori>,<thread>,<filenavn:linje>,<log tekst>
Tidsstempel altid var fra 1 til 12 kategori altid fra 14 til 15 thread altid fra 16 til 23 osv. så ville en copy(a,b) for hver del nok være hurtigere end at bruge ExtractStrings.
ja ok det kan jeg godt se....men ville så være meget låst af dette...jeg tror også den første version er hurtig nok....men jeg vil prøve med flere søgninger i flere filer...
Synes godt om
Ny brugerNybegynder
Din løsning...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.