Moja klasa obsługi logów oparta na liście jednokierunkowej:
Lista jednokierunkowa za mała pojemność. StringGrid się zawiesza przy wczytaniu dużej ilości danych.
A tu jej zmodyfikowana (moim zdaniem lepsza) wersja:
unit Logs;
{==============================================================================}
{$mode objfpc}{$H+}
{==============================================================================}
interface
{==============================================================================}
uses
Classes, SysUtils;
{==============================================================================}
// Typ określający priorytet logu.
//---------------------------
type
TPriority = (pLowest, pLow, pNormal, pHigh, pHighest);
// Typ rekordowy określający co ma zawierać log.
//----------------------------------------------
type
TLogData = packed record
Time : String[20]; // Czas w którym zapisano log.
Msg : String[100]; // Wiadomość logu.
Priority : TPriority; // Priorytet logu.
end;
// Typ uzywany w klasie do budowania listy jednokierunkowej.
//----------------------------------------------------------
type
PLogRec = ^TLogRec; // Typ wskaźnikowy.
TLogRec = record
Next : PlogRec; // Wskaźnik na nastepny rekord na liście.
Log : TLogData; // Główne dane logu.
end;
{------------------------------------------------------------------------------}
// Klasa logów pomaga zapisywać logi z różnych prac aplikacji.
//------------------------------------------------------------
type
TLogClass = class(TObject)
private
First : PLogRec; // Wskaźnik na pierwszy rekord w liście
Last : PLogRec; // Wskaźnik na ostatni rekord w liście
FileName : string; // Nazwa pliku do którego klasa zapisuje logi
LogFile : file of TLogData; // Plik do którego klasa zapisuje logi
Count : QWord; // Ilość logów na liście.
Max : QWord; // Maksymalna ilość logów na liście.
public
constructor Create(aBuff : QWord);
destructor Destroy; override;
procedure Add(aMsg : String; aPriority : TPriority);
function GetFirst : PLogRec;
procedure Clear;
procedure SaveToFile;
end;
{==============================================================================}
implementation
{==============================================================================}
// Konstruktor klasy. Nadaje wartości polom FileName (aktualna data i godzina),
// First, Last, Max, Count oraz przygotowuje plik logów do zapisu.
//------------------------------------------------------------------------------
constructor TLogClass.Create(aBuff : QWord);
begin
inherited Create;
FileName := StringReplace(DateTimeToStr(now), '-', '.', [rfReplaceAll]);
FileName := StringReplace(FileName, ':', '-', [rfReplaceAll]);
FileName := FileName + '.log';
AssignFile(LogFile, FileName);
Rewrite(LogFile);
First := nil;
Last := nil;
Max := aBuff;
Count := 0;
end;
{------------------------------------------------------------------------------}
// Destruktor klasy. Zapisuje listę do pliku, czyści ją a następnie zamyka plik.
//------------------------------------------------------------------------------
destructor TLogClass.Destroy;
begin
if First <> nil then
begin
SaveToFile;
Clear;
end;
CloseFile(LogFile);
inherited Destroy;
end;
{------------------------------------------------------------------------------}
// Dodaje log "aMsg" o priorytecie "aPriority" do listy.
// Jesli lista się przepełni jest zapisywana do pliku, a nastepnie czyszczona.
//----------------------------------------------------------------------------
procedure TLogClass.Add(aMsg : String; aPriority : TPriority);
var
NewLog : PLogRec;
begin
// Tworzenie nowego rekordu do listy
New(NewLog);
NewLog^.Log.Msg := aMsg;
NewLog^.Log.Priority := aPriority;
NewLog^.Log.Time := DateTimeToStr(Now);
NewLog^.Next := nil;
// Zwiększenie o 1 zmiennej przechowującej ilość logów na liście
Inc(Count);
// Dodanie logu na koniec listy.
if First = nil then
begin
First := NewLog;
Last := First;
end
else
begin
Last^.Next := NewLog;
Last := NewLog;
end;
// Sprawdzanie czy lista nie jest pełna.
// Jeśli tak to zapisz listę do pliku, wyczyść i ustaw ilość na 0.
if Count = Max then;
begin
SaveToFile;
Clear;
Count := 0;
end;
end;
{------------------------------------------------------------------------------}
// Zwraca wskaźnik na pierwszy element listy.
//-------------------------------------------
function TLogClass.GetFirst : PLogRec;
begin
result := First;
end;
{------------------------------------------------------------------------------}
// Czyści listę
//-------------
procedure TLogClass.Clear;
var
ToDelete : PLogRec;
begin
while First <> nil do
begin
ToDelete := First;
First := First^.Next;
Dispose(ToDelete);
end;
inherited Destroy;
end;
{------------------------------------------------------------------------------}
// Zapisuje listę do pliku
//------------------------
procedure TLogClass.SaveToFile;
var
ToSave : PLogRec;
begin
ToSave := GetFirst;
while ToSave <> nil do
begin
Write(LogFile, ToSave^.Log);
ToSave := ToSave^.Next
end;
end;
{==============================================================================}
end.
Idealna nie jest ale spełnia w 100% swoje zadanie. Przy okazji sugestie dotyczące zmian/optymalizacji mile widziane w komentarzach ;)
I tak wiem, że miałem zmienić
FileName := StringReplace(DateTimeToStr(now), '-', '.', [rfReplaceAll]);
FileName := StringReplace(FileName, ':', '-', [rfReplaceAll]);
na FormatDateTime ale najpierw chce zrozumieć tą funkcję a dopiero potem jej używać a ostatnio nie mam czasu na kodzenie.