What I want to do basically is to write log files for my VCL app. Logging procedure has to create text file on given location with name that will contain current date of writing, example is "BSSGLog 20231106.txt". In order to make it easier to go through the log files if needed I wanted to limit the entries to 1000 lines of text. If there is overflow on that current date then it has to create new file with added extension, example "BSSGLog 20231106_1.txt" etc. It works fine until it reaches extension "_9", after that it creates file with extension "_10" but it only writes one line of text and creates "_11". It keeps creating files with only one line of text until it reaches "_89". After that it works fine again. I know that the problem lies in procedure SearchFiles because it keeps checking the file with extension "_9" over and over again. This is the code to make it more easier to understand what I wanted to do.
function SearchFiles(SearchDir, SearchFile: string):String;
var
SearchRec: TSearchRec;
begin
if FindFirst(SearchDir + SearchFile, faAnyfile, SearchRec) = 0 then
begin
repeat
Result := SearchRec.Name
until (FindNext(SearchRec)<>0);
end;
FindClose(SearchRec);
end;
procedure Log(s: string);
var
FileCont: TStringList;
FileName, LogEntry: String;
fs: Tformatsettings;
i: Integer;
begin
DeleteFilesOlderThan30Days;
if not DirectoryExists(TPath.GetHomePath() + '\test') then
CreateDir(TPath.GetHomePath() + '\test');
if not DirectoryExists(TPath.GetHomePath() + '\test\Logs') then
CreateDir(TPath.GetHomePath() + '\test\Logs');
FileCont := TStringList.Create;
try
fs.ShortDateFormat := 'YYYYMMDD';
fs.TimeSeparator := ':';
if SearchFiles(TPath.GetHomePath() + '\test\Logs\', 'BSSGLog ' + DateToStr(now,fs) + '.txt') = '' then // I believe the problem lies here
begin
Filename := TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '.txt';
fileCont.SaveToFile(filename);
end
else
Filename := TPath.GetHomePath() + '\test\Logs\' + SearchFiles(TPath.GetHomePath() +
'\test\Logs\', 'BSSGLog ' + DateToStr(now,fs) + '*.txt');
FileCont.LoadFromFile(FileName);
if FileCont.Count >= 1000 then
begin
i := GetFilesCount(TPath.GetHomePath() + '\test\Logs\', 'BSSGLog ' + DateToStr(now,fs) + '*.txt');
Filename := TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '_' + i.ToString + '.txt';
FileCont.Clear();
end;
fs.ShortDateFormat := 'DD.MM.YYYY. HH:mm:ss';
LogEntry := DateTimeToStr(Now(), fs) + '- ' + s;
FileCont.Add(LogEntry);
FileCont.SaveToFile(Filename);
finally
FreeAndNil(FileCont);
end;
end;
function GetFilesCount(SearchDir, SearchFile : String) : Integer;
var
SearchRec: TSearchRec;
begin
Result := 0;
if FindFirst(SearchDir + SearchFile, faAnyFile xor faDirectory, SearchRec)= 0 then
begin
repeat
Inc(Result);
until (FindNext(SearchRec) <> 0);
FindClose(SearchRec);
end;
end;
Any advice would be highly appreciated. Maybe an idea of how to do a better job at logging. Thank you in advance!
You should get rid of the function SearchFiles
, because of the ordering problem and you should take advantage of the FileExists
function. Taking your code in account, this is how would I modify it:
try
fs.ShortDateFormat := 'YYYYMMDD';
fs.TimeSeparator := ':';
i := 0;
Filename := TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '.txt';
if not FileExists(Filename) then
begin
fileCont.SaveToFile(filename); // doesn't exist; create it
end
else
begin
if FileExists(TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '_1.txt') then
begin
i := GetFilesCount(TPath.GetHomePath() + '\test\Logs\', 'BSSGLog ' + DateToStr(now,fs) + '_*.txt');
Filename := TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '_' + i.ToString + '.txt'; // get the last file
end;
end;
FileCont.LoadFromFile(FileName);
if FileCont.Count >= 1000 then
begin
Filename := TPath.GetHomePath() + '\test\Logs\BSSGLog ' + DateToStr(Now, fs) + '_' + (i+1).ToString + '.txt'; //new file
FileCont.Clear();
end;
fs.ShortDateFormat := 'DD.MM.YYYY. HH:mm:ss';
LogEntry := DateTimeToStr(Now(), fs) + '- ' + s;
FileCont.Add(LogEntry);
FileCont.SaveToFile(Filename);
finally
FreeAndNil(FileCont);
end;
I didn't tested it. Let me know if it works for you.