Wyszukiwanie słów kluczowych tylko w plikach .log w wybranym folderze

0

Cześć, próbuję napisać aplikację, która będzie przeszukiwała pliki log w wybranym folderze w poszukiwaniu w nich słów kluczowych. Wymyśliłam sobie, że do TEdita będzie wpisywana lub wybierana ścieżka do folderu (to mi działa), (TU ZACZYNA SIĘ MÓJ PROBLEM) a później (po kliknięciu w TButton) w tej lokalizacji będzie przeszukiwała TYLKO wszystkie pliki o rozszerzeniu .log w poszukiwaniu słów kluczowych dodanych do TCheckListBox. Pewnie dałoby się to znaleźć gdzieś w internecie, ale już szukałam i nie mogę nic takiego znaleźć, wszędzie jest tylko o przeszukiwaniu konkretnego wybranego pliku, a nie o to mi chodzi.. Dopiero się uczę i wasza pomoc wiele mi pomoże

0

Musisz napisać ALGORYTM.
Niestety, edukacja w klikalnych środowiskach zabija tę umiejętność, co twój sposób wyrażenia tematu pokazuje.

Wymyśl algorytm bez obiektów wizualnych: pliki, tablice, listy itd... inaczej nigdy nie nauczysz się programować

1

Notepad++, TotalCommander, FreeCommander to potrafią i wiele innych - tzn. przeszukiwać zawartość plików i folderów w poszukiwaniu słów kluczowych, a nawet regexów. Ofc. można zawęzić się do maski jak np. pliki *.log. Jak coś z linii komend to możesz użyć narzędzi unixowych jak grep, find, awk. Nie ma potrzeby pisać tego samemu... chyba, że chcesz opanować algorytm, wtedy to co innego. Może napisz w punktach jakie kroki do wykonania widzisz. Tak po ludzki, bez kodu, a potem to się samo ułoży w kod.

0

W takim razie zacznij od czegoś prostszego - np. min, max, zamiana pozycji, sortowanie bąbelkowe, sortowanie przez wstawianie, quick sort, , wykrywanie palindromów, odwracanie wyrazów, wyszukiwanie anagramów słowa. To tak w kolejności od łatwego do trudnego. Samo szukanie wzorców jest dość trudne. Jeśli jednak chcesz pochylić się nad problemem, to dziadek Donald będzie pomocny https://pl.wikipedia.org/wiki/Algorytm_Knutha-Morrisa-Pratta

0

Jest demo w Delphi napisane do tego. Szybko wyszukuje frazy w plikach. Phrase search in delphi files.

3
J.Muzykant napisał(a):

Niestety, edukacja w klikalnych środowiskach zabija tę umiejętność, co twój sposób wyrażenia tematu pokazuje.

Środowiska z wizualnymi edytorami nie są niczemu winne — przecież w Delphi/Lazarusie jedyne co można wyklikać to interfejs (i bardzo dobrze, że jest taka możliwość). Umiejętność programowania jest zabijana przez lenistwo i poświęcanie czasu na szukanie gotowców, zamiast na nauce pisania kodu. I tak jest w tym przypadku — autorka pisze, że się uczy, ale tak naprawdę się nie uczy, bo szuka gotowców. ;)


@Alicja Kowalska: jeśli chcesz napisać ten program, to skup się przede wszystkim na właściwym algorytmie, a nie na wyglądzie okienka i jego zawartości. Do tego co potrzebujesz wystarczy procedurka, która przyjmie cztery parametry — ścieżkę katalogu do przeszukania, maskę filtrowania plików, listę zawierającą słowa kluczowe oraz listę, do której wpisze się ścieżki znalezionych plików (spełniających wymagania). Czyli w tej postaci:

procedure FindFilesWithKeywords(const APath, AMask: String; AKeywords, AResults: TStringList);

W dwóch ostatnich parametrach możesz podać dowolne listy, w tym referencje list będące właściwościami komponentów wizualnych (np. TCheckListBox.Items). Do znalezienia plików możesz skorzystać z funkcji FindFirst i FindNext, a do przeszukania zawartości pliku możesz wykorzystać listę oraz funkcję Pos, do której przekaże się TStringList.Text. Nie jest to wydajne rozwiązanie, ale na początek wystarczy.

1

W Delphi od dłuższego czasu do szybkiego i łatwego pobrania listy (a ściślej tablicy zawierającej nazwy) plików z danego folderu można użyć https://docwiki.embarcadero.com/Libraries/Sydney/en/System.IOUtils.TDirectory.GetFiles .

2
furious programming napisał(a):

Środowiska z wizualnymi edytorami nie są niczemu winne — przecież w Delphi/Lazarusie jedyne co można wyklikać to interfejs (i bardzo dobrze, że jest taka możliwość). Umiejętność programowania jest zabijana przez lenistwo i poświęcanie czasu na szukanie gotowców, zamiast na nauce pisania kodu. I tak jest w tym przypadku — autorka pisze, że się uczy, ale tak naprawdę się nie uczy, bo szuka gotowców. ;)

Mam wrażenie, że już to kiedyś pisałem ;) Jednak nie jest tak do końca jak piszesz. Domyślnie samo IDE ukierunkowuje na zawieranie logiki na formatkach i tworzenie kodu spaghetti. Chcesz zareagować na kliknięcie na button? Podwójnie kliknij go, a IDE wygeneruje pustą metodę w której zaczniesz pisać kod. Jak człowiek jest mało doświadczony, to takie coś zachęca do klepania spaghetti. Przecież dokładnie tak uczy Zelent w swoich kursach C++ Builder'a. Jak również znakomita większość kursów Delphi/C++ Builder'a.

Jednak z drugą częścią stwierdzenia zgodzę się. Pisanie dobrego i ładnie zorganizowanego kodu jest trochę bardziej pracochłonne niż pisanie takiego spaghetti. Nie mniej jednak, warto tak pisać. Ponieważ w przypadku potrzeby dokonania zmian w programie przy dobrej architekturze będą one łatwiejsze do wykonania i mniej błędogenne.

0
furious programming napisał(a):
J.Muzykant napisał(a):

Środowiska z wizualnymi edytorami nie są niczemu winne — przecież w Delphi/Lazarusie jedyne co można wyklikać to interfejs (i bardzo dobrze, że jest taka możliwość). Umiejętność programowania jest zabijana przez lenistwo i poświęcanie czasu na szukanie gotowców, zamiast na nauce pisania kodu. I tak jest w tym przypadku — autorka pisze, że się uczy, ale tak naprawdę się nie uczy, bo szuka gotowców. ;)


Że szuka gotowców, to pół prawdy.
Ale że myśli widgetami GUI a nie np strukturami danych, to już prezentuję tę skazę.
Widziałem kod - wcale nie początkujacych, a komercyjnych programistów - gdzie zamiast zmiennej gość powoływał editbox (ale, jak zauważył @Mr.YaHooo w IDE nie ma gotowego kliknięcia do powołania zmiennej. Zresztą istnieją tylko zmienne globalne, prawda? (tzw "prawda czasu, prawda ekranu")

(skądinąd, szukanie gotowca na konkretnych widgetach GUI, to naiwność, na strukturach danych są jakieś szanse)

2
J.Muzykant napisał(a):

Zresztą istnieją tylko zmienne globalne, prawda?

Że co? Widać nie masz pojęcia o czym piszesz więc lepiej już nic nie pisz....

Poza tym czy ktoś sobie naklika całą procedurę w 'OnClick', bo środowisko jest klikalne to równie dobrze tak samo może ją wklepać z palca w tym samym module odpowiadającym za interfejs aplikacji (widok) w każdym innym środowisku i kod wcale od tego nie będzie lepszy. To nie wina środowiska a programisty.

0

@kAzek:

Borlandy nie postawią adeptowi przed oczy żadnej innej zmiennej, niż globalna (oprócz argumentów funkcji). Zakładając że dla adepta coś, czego kliknąć nie można (np papierowa książka) nie istnieje ... (nie ma cię na FB, tzn nie żyjesz)

pewien Bardzo Wysoko Opłacany Programista BCB (tm) odkopiowywał zmienną globalną do drugiej, wchodził w blok, zmieniał ją, na wyjściu przywracał. Zapewniam cię, że co do zmiennych 'auto' (we frame) był dziewicą.
Chciałbyś tyle zarabiać

0

Borland już dawno nie produkuje Delphi a poza tym Nawet Delphi 1 było obiektowe więc siłą rzeczy to nie mogło się opierać tylko na zmiennych globalnych. Widziałeś może jakiegoś Turbo Pascala i myślisz, że coś wiesz o Delphi. — kAzek 6 minut temu

@kAzek
aha, co do tzw. obiektowośći: wieeeelki projekt jak stąd do Kielc, i w środku JEDNO, JEDYNE wystąpienie słowa class nie danego przez IDE czy struct - wklejka jakiegoś algorytmu z netu. Widać było to jak wielki wrzód na czole

Co do kwalifikacji, wyobraź sobie, że wiele lat pracowałem z BCB, z Delhi nieco mniej, wyciągnąłem z gó... dwa wielkie projekty, do dziś w jednym z nich jestem wspominany z szacunkiem.
Spagetti doszło nie niemożności kompilacji, czy to było 64k linii pliku, czy 64MB sursu nie pamiętam.

1

IDE generuje proste szablony do edycji. To od programisty zależy co z nim zrobi. Delphi generuje onClicki, a np. taki nowoczesny VisualStudio generuje kontrolery MVC na podstawie modelu. To od programisty zależy, czy natrzaska tam logiki, połączeń do bazy etc. czy użyje kontrolera wraz z adnotacjami do odfitrowania metod HTTP, URL'i, sparsowaniu PayLoadu do strongtypowych requestów i przekazanie to do obiektu serwisu gdzie dopiero jest logika i jakieś providery czy repa do baz. To od programisty zależy czy będzie jakiś obiekt biznesowy w Delphi, odpowiedzialny za logikę, a kod formularza będzie przekazywał input i ew. zwracać out, czy całą logikę rozsieje na eventach....

Nożem też można cheb ukroić albo kogoś zabić.

1
Mr.YaHooo napisał(a):

Domyślnie samo IDE ukierunkowuje na zawieranie logiki na formatkach i tworzenie kodu spaghetti.

Nie, z prostej przyczyny — IDE nie proponuje użytkownikowi pisania logiki w modułach formularzy. To użytkownik — z lenistwa lub niewiedzy — wszystko implementuje w zdarzeniach. Dokładnie tak samo działa VS, a patologii na taką skalę tam nie ma. Widać programiści Delphi przyzwyczajeni są do tego i ciągną to od początków istnienia narzędzi RAD.

Przecież dokładnie tak uczy Zelent w swoich kursach C++ Builder'a. Jak również znakomita większość kursów Delphi/C++ Builder'a.

Miej więc pretensje nie do narzędzia, a do autorów takich materiałów ”edukacyjnych”. ;)


J.Muzykant napisał(a):

Ale że myśli widgetami GUI a nie np strukturami danych, to już prezentuję tę skazę.

Ponownie — nie wina narzędzia, że się z niego źle korzysta.

Widziałem kod - wcale nie początkujacych, a komercyjnych programistów - gdzie zamiast zmiennej gość powoływał editbox (ale, jak zauważył @Mr.YaHooo w IDE nie ma gotowego kliknięcia do powołania zmiennej.

No to wybacz, ale widziałeś kod właśnie początkujących, bo doświadczony programista takich rzeczy nie robi.

Zresztą istnieją tylko zmienne globalne, prawda? (tzw "prawda czasu, prawda ekranu")

Ponownie wybacz, ale nie masz pojęcia o czym piszesz. I jakoś bardzo mocno kłóci mi się to z tym, co napisałeś w dalszej części, czyli z tym:

J.Muzykant napisał(a):

Co do kwalifikacji, wyobraź sobie, że wiele lat pracowałem z BCB, z Delhi nieco mniej, wyciągnąłem z gó... dwa wielkie projekty, do dziś w jednym z nich jestem wspominany z szacunkiem.

Nie wiem jakie były Twoje obowiązki w przypadku tych rzekomych projektów, ale wątpię, aby dotyczyły pracy z kodem źródłowym. Bo nie jestem sobie w stanie wyobrazić programisty, który nie ma pojęcia o takich absolutnych podstawach jak deklaracja elementów lokalnych (stałych, zmiennych, typów danych itp. itd.).

0
furious programming napisał(a):

Nie, z prostej przyczyny — IDE nie proponuje użytkownikowi pisania logiki w modułach formularzy. To użytkownik — z lenistwa lub niewiedzy — wszystko implementuje w zdarzeniach. Dokładnie tak samo działa VS, a patologii na taką skalę tam nie ma. Widać programiści Delphi przyzwyczajeni są do tego i ciągną to od początków istnienia narzędzi RAD.

W sumie racja, jednak dalej nie mam pojęcia dlaczego w takim VS czy Qt nie ma takich patologii jak w Delphi.

furious programming napisał(a):

Miej więc pretensje nie do narzędzia, a do autorów takich materiałów ”edukacyjnych”. ;)

Być może właśnie w tym tkwi problem. Swego czasu dość długo szukałem jakichś tutków czy porządnych artykułów jak pisać soft w Delphi z dobrą architekturą, ale szczerze nie znalazłem nic sensownego.

furious programming napisał(a):

Ponownie — nie wina narzędzia, że się z niego źle korzysta.

Mam wrażenie, nawet czytając wątki na naszym forum, że ludzie nie rozumieją faktu, że danych nie trzyma się w kontrolkach. Jednak to chyba po prostu lenistwo.

furious programming napisał(a):

No to wybacz, ale widziałeś kod właśnie początkujących, bo doświadczony programista takich rzeczy nie robi.

Różne rzeczy się widziało. Nawet takie gdzie wszystko było przekazywane za pomocą.... stringów. I to nie napisał jakiś junior, więc czasami ręce opadają.

0

Taaaa, stringoza to powszechny problem. Na początku lat 90 piraty produktów Borlanda były łatwo dostępne, a nie było dużej alternatywy. Programiści więc kupowali na giełdach i pisali w tym. Byli to zazwyczaj początkujący programiści. Często niestety zatrzymali się na tym poziomie, tworząc swoje produkty i firmy. Nadal jednak to nie jest poziom miliardowych korporacji, które zastanowiły się dlaczego gównianie utrzymuje się soft i to juz w latach 80. Znam gówniane projekty w Delphi (pod względem kodu, bo produkty są akceptowalne i dają spore przychody), ale znam też dobre jakościowo projekty - np. DevExpress czy mORMot, Indy, ma całkiem to sęsownie rozwiązane. Co prawda troszkę tam błędów, ale architektonicznie porządnie, aczkolwiek nietrywialnie.

Niemniej nie ma co płakać nad rozlanym mlekiem... aczkolwiek same materiały szkoleniowe Embarca czy Idera też ma kiepskie.Są co prawda bootcampy, ale kod tam pisany jest właśnie jakby wyciągnięty z lat 90... zaczynając od TEdit1 etc.

1

Młoty udarowe Makita też są do D

0

@robertz68

unit Unit1;

//{$mode objfpc}{$H+}
{$MODE Delphi}

interface

uses
 Windows, Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, Menus, IniFiles;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    ListBox1: TListBox;
    MainMenu1: TMainMenu;
    Memo1: TMemo;
    Oprogramie1: TMenuItem;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
    procedure FormCreate(Sender: TObject);
    procedure ListBox1Click(Sender: TObject);
    procedure Oprogramie1Click(Sender: TObject);
  private
  ini : TInifile;
  procedure ListaLOG(const PathName, FileName : string; const InDir : boolean);

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure Tform1.ListaLOG(const PathName, FileName : string; const InDir : boolean);
var Rec  : TSearchRec;
    Path : string;
begin
Path := IncludeTrailingBackslash(PathName);
if FindFirst(Path + FileName, faAnyFile - faDirectory, Rec) = 0 then
  try
    repeat
      ListBox1.Items.Add(Copy(Rec.Name,0,StrLen(PChar(Rec.Name)) - 4));
      INI := TIniFile.Create(ExtractFilePath(Application.ExeName)+'LOG.ini');
      iNI.WriteString('log',Copy(Rec.Name,0,StrLen(PChar(Rec.Name)) - 4),Path + Rec.Name);
      INI.Free;
    until FindNext(Rec) <> 0;
  finally
    FindClose(Rec);
  end;

if not InDir then Exit;

if FindFirst(Path + '*.*', faDirectory, Rec) = 0 then
  try
    repeat
      if (Rec.Attr in [faDirectory]) and (Rec.Name<>'.') and (Rec.Name<>'..') then
        ListaLOG(Path + Rec.Name, FileName, True);
    until FindNext(Rec) <> 0;
  finally
    FindClose(Rec);
  end;
label2.Caption := inttostr(listbox1.Items.Count);
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Info: TMenuItemInfo;
  Buff: array[0..MAX_PATH] of Char;
begin
  Info.cbSize := SizeOf(TMenuItemInfo);
  Info.fMask := MIIM_TYPE;
  Info.dwTypeData := Buff;
  Info.cch := SizeOf(Buff);
  GetMenuItemInfo(MainMenu1.Handle, Oprogramie1.Command, False, Info);
  Info.fType := Info.fType or MFT_RIGHTJUSTIFY;
  SetMenuItemInfo(MainMenu1.Handle, Oprogramie1.Command, False, Info);
end;

procedure TForm1.ListBox1Click(Sender: TObject);
var SF, ToOpen: String;
i : integer;
begin
  INI := TIniFile.Create(ExtractFilePath(Application.ExeName)+'lOG.ini');
  SF := ListBox1.Items.Strings[ListBox1.ItemIndex];
  ToOpen := INI.ReadString('LOG',SF,'');
  Memo1.Lines.LoadFromFile(ToOpen);
  INI.Free;
end;

procedure TForm1.Oprogramie1Click(Sender: TObject);
begin
  Showmessage('I Ty możesz napisać takie coś :-) Pozdrawiam Mariusz Bruniewski');
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Clear;
ListaLOG('C:\','*.log',True);
label4.Caption := 'GOTOWE !!!';
end;

procedure TForm1.Button2Click(Sender: TObject);
var
  I, L: Integer;
begin
  Memo1.WordWrap:= False;
  I:= Pos(Edit1.Text, Memo1.Text);
  if I > 0 then begin
    L := SendMessage(Memo1.Handle, EM_LINEFROMCHAR, I - 1, 0);
    label1.Caption := ('Znaki w linii ' + IntToStr(L));
    Memo1.SelStart := I - 1;
    Memo1.SelLength := Length(Edit1.Text);
    Memo1.SetFocus;
  end;
end;

procedure TForm1.FormClose(Sender: TObject; var CloseAction: TCloseAction);
begin
  Deletefile('Log.ini');
end;

end.

log.JPGlog.JPG

0

@Mariusz Bruniewski:
Zawarcie logiki w metodach formyi to zły przykład, owszem można tak zrobić ale jest to antywzorzec projektowy.
Nawet programując proceduralnie można utworzyć funkcję np. :

function searachPattern(aDir,aFilenameMask,aPattern:string;aIncludeSubDirs:boolean:aResult:Stringtlist):integer;
begin 
  aResult.clear;
   ////
  /// tutaj algorytm wyszukiwania plików
  /// . ...........
  ///
  result:=aResult.count;
  /// 
end;

która zwraca liczbę plików zawierających aPattern a w aResult jest lista plików

lTsResult:=tstringlist.create;
try
  if searachPattern('c:\','*.log','jakis tekst',true,lTsResult)>0 then 
    self.memo.lines.text:=lTsResult.text
  else
    self.memo.lines.text:='Nic nie znaleziono';
filnlly
  lTsResult.free;
end;
0

@Mariusz Bruniewski:
chciałem usunąć komentarz a przez pomyłkę usunąłem cały post więc powtórzę

To po się czepasziasz i nic nie wnosisisz w mój kod

Podałem schemat rozwiązania separującego logikę od od interfejsu użytkownika.
Publikujesz kod na publicznym portalu więc nie oczekuj że dostaniesz tylko oklaski.
Twój kod może i działa, ale jest antywzorcem programowania

1 użytkowników online, w tym zalogowanych: 0, gości: 1