Tuesday, November 26, 2024

Delphi logging

In my Delphi programs, I often have the need (or desire) to write data to a logfile which is a simple text file. I've always used the following code that is based on "old style Pascal I/O".

procedure TMainForm.Write2Log (const s: string); var f: textfile; begin assignfile (f, logfilename); if fileexists (logfilename) then append (f) else rewrite (f); writeln (f, datetimetostr (now), ' ', s); flush (f); closefile (f); end;

For reasons that I have never been able to establish, this sort of code is frowned upon by some Delphi developers. I have eventually got around to converting the procedure to regular Delphi code.

procedure TMainForm.Write2Log (const s: string); // the Delphi way var outstring: string; fs: TStream; begin if not fileexists (logfilename) then fs:= TFileStream.Create (logfilename, fmCreate OR fmShareDenyNone) else begin fs:= TFileStream.Create (logfilename, fmOpenWrite OR fmShareDenyNone); fs.Position:= fs.Size end; try outstring:= datetimetostr (now) + #9 + s + #13#10; fs.WriteBuffer (outstring[1], length (outstring)) finally fs.Free end end;

To me, this seems unnecessarily low level - adding the tab, carriage return and line feed to the string and passing the length of the string to be output. There is also a small bug in that code - in unicode days, length (outstring) is not equal to the number of bytes to be output. But I'm writing non-unicode programs, so I'll get by. 

I wondered whether it's possible to create the stream on program startup - thus there will be no need to destroy the steam each time. Of course, the end of the file has to be 'seeked' (or in English, sought). Although this works, no other program is able to open the log, somewhat negating the whole idea of a logfile.

As it happens, variations of my old-style code can be found on the Internet, for example here, although it should be pointed out that the linked article is from 2005. Various techniques are shown, but as all I want/need to do is append a line at the end of the file, reading the file (e.g. stringlist.loadfromfile) then adding the line and writing it back to disk (stringlist.savetofile) seems like overkill, especially if the file has many lines.

Incidentally, an alternative version uses Pointer (outstring)^ instead of str[1]; although the result is the same, some consider that using the typecast to pointer makes it more clear what the expression is (the first character in the string). I'm not so sure.



This day in history:

Blog #
Date
TitleTags
144326/11/2021
Opening Excel from a thread and displaying a fileProgramming, Delphi, Office automation, Threads
169026/11/2023
Guitar thoughtsGuitars

No comments: